Các tài liệu phụ Mongoose so với lược đồ lồng nhau


122

Tôi tò mò về những ưu và nhược điểm của việc sử dụng các tài liệu phụ so với một lớp sâu hơn trong lược đồ chính của tôi:

var subDoc = new Schema({
  name: String
});

var mainDoc = new Schema({
  names: [subDoc]
});

hoặc là

var mainDoc = new Schema({
  names: [{
    name: String
 }]
});

Tôi hiện đang sử dụng tài liệu phụ ở khắp mọi nơi nhưng tôi chủ yếu thắc mắc về hiệu suất hoặc các vấn đề truy vấn mà tôi có thể gặp phải.


Tôi đang cố gắng nhập câu trả lời cho bạn, nhưng tôi không thể tìm thấy cách nào. Nhưng hãy xem tại đây: mongoosejs.com/docs/subdocs.html
gustavohenke Ngày

Dưới đây là một phản ứng tốt về cân nhắc MongoDB tự hỏi mình khi tạo CSDL của bạn: stackoverflow.com/questions/5373198/...
anthonylawson

Bạn có nghĩa là nó cũng cần phải mô tả _idtrường? Ý tôi là, nó không tự động nếu nó được bật?
Vadorequest

có ai biết nếu _idlĩnh vực của các tài liệu là duy nhất? (được tạo bằng cách sử dụng cách thứ 2 trong câu hỏi của OP)
Saitama

Câu trả lời:


72

Theo các tài liệu , nó hoàn toàn giống nhau. Tuy nhiên, việc sử dụng một Lược đồ cũng sẽ thêm một _idtrường (miễn là bạn không vô hiệu hóa trường đó) và có lẽ sử dụng thêm một số tài nguyên để theo dõi tài nguyên con.

Cú pháp khai báo thay thế

Tính năng mới trong phiên bản v3 Nếu bạn không cần quyền truy cập vào phiên bản lược đồ tài liệu con, bạn cũng có thể khai báo tài liệu con bằng cách chuyển một đối tượng theo nghĩa đen [...]


1
Nhưng tôi đã thử điều này. Tại sao dữ liệu tài liệu con không được lưu trữ trong bộ sưu tập riêng biệt. Nó luôn lưu trữ bên trong bộ sưu tập MainDoc.
Fizer Khan

17
đó là cách hoạt động của các tài liệu phụ. họ đang nhúng bên trong tài liệu. trước khi chơi với mongoose, hãy đảm bảo rằng bạn hiểu MongoDB cơ bản.
AndyL

1
Về việc Lược đồ thêm _id, điều đó có lý nhưng tôi đã tạo một lược đồ với một mảng tài liệu con và một mảng các ký tự đối tượng và một _id đã được thêm vào cả hai. Hành vi có thay đổi không?
Drew Goodwin

@DrewGoodwin có vẻ như nó đã như thế này trong một thời gian: stackoverflow.com/questions/17254008/…
cheesemacfly

37

Nếu bạn có các lược đồ được sử dụng lại trong các phần khác nhau của mô hình, thì việc xác định các lược đồ riêng lẻ cho các tài liệu con có thể hữu ích để bạn không phải tự sao chép.


4
Đây là một câu trả lời tuyệt vời. Đôi khi tôi sử dụng các tài liệu con trong nhiều mô hình đó hoặc tôi có hai trường trong một mô hình cần được phân biệt, nhưng vẫn có cùng cấu trúc tài liệu con.
Martin Hallén

2
bạn cũng nên xem xét lợi ích / bất lợi của việc lưu thông tin dư thừa.
Sam Vloeberghs

25

Bạn nên sử dụng tài liệu nhúng nếu đó là tài liệu tĩnh hoặc không quá vài trăm vì ảnh hưởng đến hiệu suất. Tôi đã trải qua vấn đề đó một thời gian trước. Mới đây, Asya Kamsky, người làm việc với tư cách là kiến ​​trúc sư giải pháp cho MongoDB đã viết một bài báo về "sử dụng các tài liệu phụ".

Tôi hy vọng điều đó sẽ giúp ích cho những ai đang tìm kiếm giải pháp hoặc phương pháp tốt nhất.

Bài gốc trên http://askasya.com/post/largeembeddedarrays . Bạn có thể truy cập hồ sơ stackoverflow của cô ấy trên https://stackoverflow.com/users/431012/asya-kamsky

Trước hết, chúng ta phải xem xét tại sao chúng ta lại muốn làm một điều như vậy. Thông thường, tôi khuyên mọi người nên nhúng những thứ mà họ luôn muốn lấy lại khi tìm nạp tài liệu này. Mặt trái của điều này là bạn không muốn nhúng những thứ vào tài liệu mà bạn không muốn lấy lại nó.

Nếu bạn nhúng hoạt động tôi thực hiện vào tài liệu, lúc đầu nó sẽ hoạt động tốt vì tất cả hoạt động của tôi đều ở ngay đó và chỉ với một lần đọc, bạn có thể lấy lại mọi thứ bạn có thể muốn cho tôi xem: "gần đây bạn đã nhấp vào cái này và ở đây là hai nhận xét cuối cùng của bạn "nhưng điều gì sẽ xảy ra sau sáu tháng trôi qua và tôi không quan tâm đến những việc tôi đã làm từ lâu và bạn không muốn cho tôi xem trừ khi tôi đặc biệt đi tìm hoạt động cũ?

Đầu tiên, bạn sẽ trả về tài liệu lớn hơn và lớn hơn và quan tâm đến phần nhỏ hơn và nhỏ hơn của nó. Nhưng bạn có thể sử dụng phép chiếu để chỉ trả về một số mảng, điều thực sự khó khăn là tài liệu trên đĩa sẽ lớn hơn và tất cả sẽ vẫn được đọc ngay cả khi bạn chỉ trả lại một phần của nó cho người dùng cuối, nhưng vì hoạt động của tôi sẽ không ngừng nếu tôi còn hoạt động, tài liệu sẽ tiếp tục phát triển và phát triển.

Vấn đề rõ ràng nhất với điều này là cuối cùng bạn sẽ đạt đến giới hạn tài liệu 16MB, nhưng đó không phải là điều bạn nên lo lắng. Một tài liệu liên tục phát triển sẽ phải chịu chi phí ngày càng cao mỗi khi nó phải được di chuyển lại trên đĩa và ngay cả khi bạn thực hiện các bước để giảm thiểu tác động của phân mảnh, việc ghi của bạn nhìn chung sẽ dài không cần thiết, ảnh hưởng đến hiệu suất tổng thể của toàn bộ ứng dụng của bạn.

Có một điều nữa mà bạn có thể làm sẽ giết chết hoàn toàn hiệu suất ứng dụng của bạn và đó là lập chỉ mục cho mảng ngày càng tăng này. Điều đó có nghĩa là mỗi khi tài liệu có mảng này được di dời, số lượng mục nhập chỉ mục cần được cập nhật tỷ lệ thuận với số lượng giá trị được lập chỉ mục trong tài liệu đó và mảng càng lớn thì số lượng đó sẽ càng lớn là.

Tôi không muốn điều này làm bạn sợ sử dụng mảng khi chúng phù hợp với mô hình dữ liệu - chúng là một tính năng mạnh mẽ của mô hình dữ liệu cơ sở dữ liệu tài liệu, nhưng giống như tất cả các công cụ mạnh mẽ, nó cần được sử dụng trong những trường hợp thích hợp và nó nên được sử dụng cẩn thận.


3
Đây phải là câu trả lời hàng đầu; nó đập vào tiền. Sách trắng của MongoDB nói khá nhiều điều tương tự.
Jay Edwards

Bài báo này về Mô hình xô khen ngợi những gì Asya nói về một cách độc đáo. mongodb.com/blog/post/building-with-patterns-the-bucket-pattern Tôi nghĩ giản đồ subDoc trong câu hỏi của OP sẽ hoạt động tốt với Bucket Pattern.
plong0

13

Về cơ bản, hãy tạo một biến nestedDovvà đặt nó ở đâyname: [nestedDov]

Phiên bản đơn giản:

var nestedDoc = new Schema({
  name: String
});

var mainDoc = new Schema({
  names: [nestedDoc]
});

Ví dụ về JSON

{
    "_id" : ObjectId("57c88bf5818e70007dc72e85"),
    "name" : "Corinthia Hotel Budapest",
    "stars" : 5,
    "description" : "The 5-star Corinthia Hotel Budapest on the Grand Boulevard offers free access to its Royal Spa",
    "photos" : [
        "/photos/hotel/corinthiahotelbudapest/1.jpg",
        "/photos/hotel/corinthiahotelbudapest/2.jpg"
    ],
    "currency" : "HUF",
    "rooms" : [
        {
            "type" : "Superior Double or Twin Room",
            "number" : 20,
            "description" : "These are some great rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/2.jpg",
                "/photos/room/corinthiahotelbudapest/5.jpg"
            ],
            "price" : 73000
        },
        {
            "type" : "Deluxe Double Room",
            "number" : 50,
            "description" : "These are amazing rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/4.jpg",
                "/photos/room/corinthiahotelbudapest/6.jpg"
            ],
            "price" : 92000
        },
        {
            "type" : "Executive Double Room",
            "number" : 25,
            "description" : "These are amazing rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/4.jpg",
                "/photos/room/corinthiahotelbudapest/6.jpg"
            ],
            "price" : 112000
        }
    ],
    "reviews" : [
        {
            "name" : "Tamas",
            "id" : "/user/tamas.json",
            "review" : "Great hotel",
            "rating" : 4
        }
    ],
    "services" : [
        "Room service",
        "Airport shuttle (surcharge)",
        "24-hour front desk",
        "Currency exchange",
        "Tour desk"
    ]
}

Thí dụ:

nhập mô tả hình ảnh ở đây


1
Điều đó không giải quyết được câu hỏi đâu là hiệu suất.
cyberwombat

Tôi đã chỉnh sửa một chút để có ý nghĩa hơn. Bạn nghĩ sao?
Wayne Chiu

3
Câu hỏi không phải là hỏi làm thế nào để thực hiện các lược đồ lồng nhau. Nó là một cuộc thảo luận về việc liệu Mongoose có hiệu quả hơn với các lược đồ lồng nhau hoặc các tài liệu con được nhúng hay không. Về cơ bản, chúng ta đang nói về điểm chuẩn hoặc các loại hoặc các trường hợp cạnh mà Mongoose thích cái này hơn cái kia. Và như câu trả lời đã chọn đề cập, nó dường như không tạo ra bất kỳ sự khác biệt nào, ít nhất là từ V3 trở đi.
cyberwombat

17
Có thể không hoạt động cho OP, nhưng tôi thấy điều này rất hữu ích. Cảm ơn.
Gene Higgins

Điều này là tốt khi cả 3 lược đồ được khai báo trong một tệp .js, làm thế nào chúng ta có thể xử lý nó khi khai báo trong 3 tệp .js khác nhau?
Satyam

9

Tôi nghĩ rằng điều này được xử lý ở nơi khác bởi nhiều bài đăng trên SO.

Chỉ một vài:

Chìa khóa lớn là không có câu trả lời duy nhất ở đây, chỉ có một tập hợp các đánh đổi khá phức tạp.


3
Có lẽ tôi đang diễn giải câu hỏi của mình không chính xác - Đây không phải là câu hỏi về cách tôi nên cấu trúc cơ sở dữ liệu của mình mà là nội dung của việc sử dụng một subchema so với chỉ viết mảng trong một lớp sâu hơn. Nguyên nhân chính của tôi khi sử dụng một địa chỉ con là vì tôi có thể sử dụng các loại lược đồ tùy chỉnh và yêu cầu chúng xác thực - một thứ không hoạt động với các mảng lồng nhau (từ một câu hỏi trước đây tôi đã có trên SO). Gần như tôi có thể nói rằng một suboc khá giống với một mảng lồng nhau - tôi chỉ không biết nội dung bên trong của nó - nếu sử dụng chúng sẽ tạo ra các vấn đề về hiệu suất hoặc tương tự.
cyberwombat

0

Có một số khác biệt giữa hai:

  • Sử dụng lược đồ lồng nhau rất hữu ích cho việc xác nhận.

  • Lược đồ lồng nhau có thể được sử dụng lại trong các lược đồ khác.

  • Lược đồ lồng nhau thêm trường '_id' vào tài liệu con trừ khi bạn sử dụng "_id: false"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.