Tham chiếu tài liệu mongodb
Khung ánh xạ không phải lưu trữ các đối tượng con được nhúng trong tài liệu. Bạn cũng có thể lưu trữ chúng riêng biệt và sử dụng Account account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();5 để tham khảo tài liệu đó. Khi đối tượng được tải từ MongoDB, các tham chiếu đó sẽ được giải quyết một cách háo hức để bạn lấy lại một đối tượng được ánh xạ trông giống như thể nó đã được lưu trữ nhúng trong tài liệu cấp cao nhất của bạn Ví dụ sau đây sử dụng DBRef để tham chiếu đến một tài liệu cụ thể tồn tại độc lập với đối tượng mà nó được tham chiếu (cả hai lớp được hiển thị trong dòng vì lý do ngắn gọn) @Document public class Account { @Id private ObjectId id; private Float total; } @Document public class Person { @Id private ObjectId id; @Indexed private Integer ssn; @DBRef private List<Account> accounts; } Bạn không cần sử dụng Account account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();6 hoặc các cơ chế tương tự vì Danh sách các đối tượng cho khung ánh xạ biết rằng bạn muốn có mối quan hệ một-nhiều. Khi đối tượng được lưu trữ trong MongoDB, sẽ có một danh sách các DBRef thay vì chính các đối tượng Account account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();7. Khi nói đến việc tải các bộ sưu tập của Account account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();5, nên hạn chế các tham chiếu được giữ trong các loại bộ sưu tập đối với một bộ sưu tập MongoDB cụ thể. Điều này cho phép tải hàng loạt tất cả các tham chiếu, trong khi các tham chiếu trỏ đến các bộ sưu tập MongoDB khác nhau cần được giải quyết từng cái một Quan trọng Khung ánh xạ không xử lý lưu theo tầng. Nếu bạn thay đổi một đối tượngAccount account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();7 được tham chiếu bởi một đối tượng { "_id" : …, "accounts" : [ "6509b9e" … ] (4) }0, bạn phải lưu riêng đối tượng Account account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();7. Việc gọi { "_id" : …, "accounts" : [ "6509b9e" … ] (4) }2 trên đối tượng { "_id" : …, "accounts" : [ "6509b9e" … ] (4) }0 không tự động lưu các đối tượng Account account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();7 trong thuộc tính { "_id" : …, "accounts" : [ "6509b9e" … ] (4) }5 Account account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();5s cũng có thể được giải quyết một cách lười biếng. Trong trường hợp này, { "_id" : …, "accounts" : [ "6509b9e" … ] (4) }7 hoặc { "_id" : …, "accounts" : [ "6509b9e" … ] (4) }8 thực tế của tham chiếu được giải quyết trong lần truy cập đầu tiên vào thuộc tính. Sử dụng thuộc tính { "_id" : …, "accounts" : [ "6509b9e" … ] (4) }9 của @Document class Book { @Id ObjectId id; String title; List<String> author; @Field("publisher_ac") @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") (1) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; @DocumentReference(lazy = true) (2) List<Book> books; }0 để chỉ định điều này. Các thuộc tính bắt buộc cũng được định nghĩa là lazy loading Account account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();5 và được sử dụng làm đối số hàm tạo cũng được trang trí bằng proxy lazy loading để đảm bảo gây ít áp lực nhất có thể lên cơ sở dữ liệu và mạng Mẹo Có thể khó gỡ lỗi cácAccount account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();5 được tải chậm. Đảm bảo rằng công cụ không vô tình kích hoạt độ phân giải proxy bởi e. g. gọi @Document class Book { @Id ObjectId id; String title; List<String> author; @Field("publisher_ac") @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") (1) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; @DocumentReference(lazy = true) (2) List<Book> books; }3 hoặc một số hiển thị gỡ lỗi nội tuyến gọi trình nhận thuộc tính. Vui lòng cân nhắc bật ghi nhật ký theo dõi cho @Document class Book { @Id ObjectId id; String title; List<String> author; @Field("publisher_ac") @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") (1) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; @DocumentReference(lazy = true) (2) List<Book> books; }4 để hiểu rõ hơn về giải pháp Account account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();5 thận trọng Tải chậm có thể yêu cầu proxy lớp, do đó, có thể cần quyền truy cập vào nội bộ jdk, không mở, bắt đầu với Java 16+, do JEP 396. Đóng gói mạnh mẽ nội bộ JDK theo mặc định. Đối với những trường hợp đó, vui lòng xem xét quay lại loại giao diện (ví dụ:. chuyển từ@Document class Book { @Id ObjectId id; String title; List<String> author; @Field("publisher_ac") @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") (1) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; @DocumentReference(lazy = true) (2) List<Book> books; }6 sang @Document class Book { @Id ObjectId id; String title; List<String> author; @Field("publisher_ac") @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") (1) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; @DocumentReference(lazy = true) (2) List<Book> books; }7) hoặc cung cấp đối số @Document class Book { @Id ObjectId id; String title; List<String> author; @Field("publisher_ac") @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") (1) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; @DocumentReference(lazy = true) (2) List<Book> books; }8 bắt buộc Sử dụng tài liệu tham khảoSử dụng @Document class Book { @Id ObjectId id; String title; List<String> author; @Field("publisher_ac") @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") (1) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; @DocumentReference(lazy = true) (2) List<Book> books; }9 cung cấp một cách linh hoạt để tham chiếu các thực thể trong MongoDB. Mặc dù mục tiêu giống như khi sử dụng , nhưng biểu diễn cửa hàng thì khác. Account account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();5 phân giải thành tài liệu có cấu trúc cố định như được nêu trong tài liệu tham khảo MongoDB Tài liệu tham khảo, không theo một định dạng cụ thể. Chúng có thể là bất cứ thứ gì theo đúng nghĩa đen, một giá trị đơn lẻ, toàn bộ tài liệu, về cơ bản là mọi thứ có thể được lưu trữ trong MongoDB. Theo mặc định, lớp ánh xạ sẽ sử dụng giá trị id của thực thể được tham chiếu để lưu trữ và truy xuất, như trong mẫu bên dưới @Document class Account { @Id String id; Float total; } @Document class Person { @Id String id; @DocumentReference (1) List<Account> accounts; } Account account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first(); { "_id" : …, "accounts" : [ "6509b9e" … ] (4) }
Mẫu ở trên sử dụng truy vấn tìm nạp dựa trên { "_id" : 9a48e32, "title" : "The Warded Man", "author" : ["Peter V. Brett"], "publisher_ac" : "DR" }3 ( { "_id" : 9a48e32, "title" : "The Warded Man", "author" : ["Peter V. Brett"], "publisher_ac" : "DR" }5) để truy xuất dữ liệu và giải quyết các thực thể được liên kết một cách háo hức. Có thể thay đổi mặc định độ phân giải (được liệt kê bên dưới) bằng cách sử dụng các thuộc tính của @Document class Book { @Id ObjectId id; String title; List<String> author; @Field("publisher_ac") @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") (1) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; @DocumentReference(lazy = true) (2) List<Book> books; }9Bảng 1. @DocumentReference defaultsAttributeDescriptionDefault { "_id" : 9a48e32, "title" : "The Warded Man", "author" : ["Peter V. Brett"], "publisher_ac" : "DR" }7 Tên cơ sở dữ liệu đích để tra cứu bộ sưu tập { "_id" : 9a48e32, "title" : "The Warded Man", "author" : ["Peter V. Brett"], "publisher_ac" : "DR" }8 { "_id" : 9a48e32, "title" : "The Warded Man", "author" : ["Peter V. Brett"], "publisher_ac" : "DR" }9 Tên bộ sưu tập mục tiêu Loại miền của thuộc tính được chú thích, tương ứng là loại giá trị trong trường hợp thuộc tính { "_id" : …, "accounts" : [ "6509b9e" … ] (4) }8 like hoặc { "_id" : 1a23e45, "acronym" : "DR", "name" : "Del Rey", … }1, tên bộ sưu tập { "_id" : 1a23e45, "acronym" : "DR", "name" : "Del Rey", … }2 Truy vấn tra cứu tài liệu duy nhất đánh giá các trình giữ chỗ thông qua các biểu thức SpEL bằng cách sử dụng { "_id" : 1a23e45, "acronym" : "DR", "name" : "Del Rey", … }3 làm điểm đánh dấu cho một giá trị nguồn đã cho. Các thuộc tính { "_id" : …, "accounts" : [ "6509b9e" … ] (4) }8 like hoặc { "_id" : 1a23e45, "acronym" : "DR", "name" : "Del Rey", … }1 kết hợp các tra cứu riêng lẻ thông qua toán tử { "_id" : 1a23e45, "acronym" : "DR", "name" : "Del Rey", … }6 Truy vấn dựa trên trường { "_id" : 9a48e32, "title" : "The Warded Man", "author" : ["Peter V. Brett"], "publisher_ac" : "DR" }3 (_______32_______5) sử dụng giá trị nguồn đã tải { "_id" : 1a23e45, "acronym" : "DR", "name" : "Del Rey", … }9 Được sử dụng để phân loại tài liệu kết quả ở phía máy chủ Không theo mặc định. Thứ tự kết quả của { "_id" : …, "accounts" : [ "6509b9e" … ] (4) }8 thuộc tính tương tự được khôi phục dựa trên truy vấn tra cứu đã sử dụng trên cơ sở nỗ lực tối đa { "_id" : …, "accounts" : [ "6509b9e" … ] (4) }9 Nếu được đặt thành @WritingConverter class PublisherReferenceConverter implements Converter<Publisher, DocumentPointer<String>> { @Override public DocumentPointer<String> convert(Publisher source) { return () -> source.getAcronym(); } }2, việc giải quyết giá trị bị trì hoãn khi truy cập thuộc tính lần đầu Giải quyết các thuộc tính một cách háo hức theo mặc định thận trọng Tải chậm có thể yêu cầu proxy lớp, do đó, có thể cần quyền truy cập vào nội bộ jdk, không mở, bắt đầu với Java 16+, do JEP 396. Đóng gói mạnh mẽ nội bộ JDK theo mặc định. Đối với những trường hợp đó, vui lòng xem xét quay lại loại giao diện (ví dụ:. chuyển từ@Document class Book { @Id ObjectId id; String title; List<String> author; @Field("publisher_ac") @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") (1) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; @DocumentReference(lazy = true) (2) List<Book> books; }6 sang @Document class Book { @Id ObjectId id; String title; List<String> author; @Field("publisher_ac") @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") (1) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; @DocumentReference(lazy = true) (2) List<Book> books; }7) hoặc cung cấp đối số @Document class Book { @Id ObjectId id; String title; List<String> author; @Field("publisher_ac") @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") (1) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; @DocumentReference(lazy = true) (2) List<Book> books; }8 bắt buộc @WritingConverter class PublisherReferenceConverter implements Converter<Publisher, DocumentPointer<String>> { @Override public DocumentPointer<String> convert(Publisher source) { return () -> source.getAcronym(); } }6 cho phép xác định các truy vấn bộ lọc có thể khác với trường { "_id" : 9a48e32, "title" : "The Warded Man", "author" : ["Peter V. Brett"], "publisher_ac" : "DR" }3 và do đó cung cấp một cách linh hoạt để xác định các tham chiếu giữa các thực thể như được minh họa trong mẫu bên dưới, trong đó @WritingConverter class PublisherReferenceConverter implements Converter<Publisher, DocumentPointer<String>> { @Override public DocumentPointer<String> convert(Publisher source) { return () -> source.getAcronym(); } }8 của một cuốn sách được tham chiếu bằng từ viết tắt của nó thay vì nội bộ @WritingConverter class PublisherReferenceConverter implements Converter<Publisher, DocumentPointer<String>> { @Override public DocumentPointer<String> convert(Publisher source) { return () -> source.getAcronym(); } }9 @Document class Book { @Id ObjectId id; String title; List<String> author; @Field("publisher_ac") @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") (1) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; @DocumentReference(lazy = true) (2) List<Book> books; } @Document class Book { @Id ObjectId id; String title; List<String> author; @DocumentReference(lookup = "{ 'acronym' : ?#{acc} }") (1) (2) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; // ... }0 tài liệu { "_id" : 9a48e32, "title" : "The Warded Man", "author" : ["Peter V. Brett"], "publisher_ac" : "DR" } Tài liệu @WritingConverter class PublisherReferenceConverter implements Converter<Publisher, DocumentPointer<String>> { @Override public DocumentPointer<String> convert(Publisher source) { return () -> source.getAcronym(); } }8 { "_id" : 1a23e45, "acronym" : "DR", "name" : "Del Rey", … }
Đoạn mã trên cho thấy khía cạnh đọc của mọi thứ khi làm việc với các đối tượng được tham chiếu tùy chỉnh. Viết yêu cầu một chút thiết lập bổ sung vì thông tin ánh xạ không thể hiện nơi mà { "_id" : 1a23e45, "acronym" : "DR", "name" : "Del Rey", … }3 bắt nguồn từ. Lớp ánh xạ yêu cầu đăng ký một @Document class Book { @Id ObjectId id; String title; List<String> author; @DocumentReference(lookup = "{ 'acronym' : ?#{acc} }") (1) (2) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; // ... }6 giữa tài liệu đích và @Document class Book { @Id ObjectId id; String title; List<String> author; @DocumentReference(lookup = "{ 'acronym' : ?#{acc} }") (1) (2) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; // ... }7, giống như bên dưới @WritingConverter class PublisherReferenceConverter implements Converter<Publisher, DocumentPointer<String>> { @Override public DocumentPointer<String> convert(Publisher source) { return () -> source.getAcronym(); } } Nếu không cung cấp bộ chuyển đổi @Document class Book { @Id ObjectId id; String title; List<String> author; @DocumentReference(lookup = "{ 'acronym' : ?#{acc} }") (1) (2) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; // ... }7, tài liệu tham chiếu đích có thể được tính toán dựa trên truy vấn tra cứu đã cho. Trong trường hợp này, các thuộc tính mục tiêu liên kết được đánh giá như trong mẫu sau @Document class Book { @Id ObjectId id; String title; List<String> author; @DocumentReference(lookup = "{ 'acronym' : ?#{acc} }") (1) (2) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; // ... } { "_id" : 9a48e32, "title" : "The Warded Man", "author" : ["Peter V. Brett"], "publisher" : { "acc" : "DOC" } }
Cũng có thể mô hình hóa các tham chiếu One-To-Many kiểu quan hệ bằng cách sử dụng kết hợp { "_id" : 9a48e32, "title" : "The Warded Man", "author" : ["Peter V. Brett"], "publisher" : { "acc" : "DOC" } }2 và @Document class Book { @Id ObjectId id; String title; List<String> author; @Field("publisher_ac") @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") (1) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; @DocumentReference(lazy = true) (2) List<Book> books; }9. Cách tiếp cận này cho phép các loại liên kết không lưu trữ các giá trị liên kết trong tài liệu sở hữu mà lưu trữ trên tài liệu tham chiếu như trong ví dụ bên dưới @Document class Account { @Id String id; Float total; } @Document class Person { @Id String id; @DocumentReference (1) List<Account> accounts; }0 @Document class Book { @Id ObjectId id; String title; List<String> author; @DocumentReference(lookup = "{ 'acronym' : ?#{acc} }") (1) (2) Publisher publisher; } @Document class Publisher { @Id ObjectId id; String acronym; (1) String name; // ... }0 tài liệu @Document class Account { @Id String id; Float total; } @Document class Person { @Id String id; @DocumentReference (1) List<Account> accounts; }1 Tài liệu @WritingConverter class PublisherReferenceConverter implements Converter<Publisher, DocumentPointer<String>> { @Override public DocumentPointer<String> convert(Publisher source) { return () -> source.getAcronym(); } }8 @Document class Account { @Id String id; Float total; } @Document class Person { @Id String id; @DocumentReference (1) List<Account> accounts; }2
Với tất cả những điều trên, có thể mô hình hóa tất cả các loại liên kết giữa các thực thể. Hãy xem danh sách mẫu chưa đầy đủ bên dưới để cảm nhận về những gì có thể ví dụ 1. Tham khảo tài liệu đơn giản sử dụng trường id @Document class Account { @Id String id; Float total; } @Document class Person { @Id String id; @DocumentReference (1) List<Account> accounts; }3 @Document class Account { @Id String id; Float total; } @Document class Person { @Id String id; @DocumentReference (1) List<Account> accounts; }4
ví dụ 2. Tham khảo tài liệu đơn giản sử dụng trường id với truy vấn tra cứu rõ ràng @Document class Account { @Id String id; Float total; } @Document class Person { @Id String id; @DocumentReference (1) List<Account> accounts; }5 @Document class Account { @Id String id; Float total; } @Document class Person { @Id String id; @DocumentReference (1) List<Account> accounts; }6
ví dụ 3. Tài liệu tham khảo trích xuất trường @Document class Account { @Id String id; Float total; } @Document class Person { @Id String id; @DocumentReference (1) List<Account> accounts; }06 cho truy vấn tra cứu @Document class Account { @Id String id; Float total; } @Document class Person { @Id String id; @DocumentReference (1) List<Account> accounts; }7 @Document class Account { @Id String id; Float total; } @Document class Person { @Id String id; @DocumentReference (1) List<Account> accounts; }8 @Document class Account { @Id String id; Float total; } @Document class Person { @Id String id; @DocumentReference (1) List<Account> accounts; }9
Ví dụ 4. Tài liệu tham khảo với nhiều giá trị tạo thành truy vấn tra cứu Account account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();0 Account account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();1
Ví dụ 5. Tài liệu tham khảo đọc từ một bộ sưu tập mục tiêu Account account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();2 Account account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();3 Account account = … tempate.insert(account); (2) template.update(Person.class) .matching(where("id").is(…)) .apply(new Update().push("accounts").value(account)) (3) .first();4
Cảnh báo Chúng tôi biết rằng việc sử dụng tất cả các loại toán tử truy vấn MongoDB trong truy vấn tra cứu là rất hấp dẫn và điều này tốt. Nhưng có một vài khía cạnh để xem xét
Một vài nhận xét chung hơn
|