2013-03-04 220 views
78

我很好奇的優點和使用子文檔VS更深一層在我的主要模式的利弊:貓鼬子文檔VS嵌套模式

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

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

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

我目前使用各地的小組,但我主要想知道性能或查詢我可能遇到的問題。

+0

我想輸入一個答案給你,但我找不到如何。但請看看這裏:http://mongoosejs.com/docs/subdocs.html – gustavohenke 2013-03-04 20:26:44

+0

下面是關於MongoDB注意事項的一個很好的回答,以便在創建數據庫模式時自問:http:// stackoverflow。com/questions/5373198/a-simple-mongodb-question-embed-or-reference – anthonylawson 2013-03-04 20:41:40

+0

你的意思是它還需要描述'_i​​d'字段?我的意思是,如果啓用它不是自動的? – Vadorequest 2014-02-08 19:02:46

回答

42

根據the docs,它是完全一樣的。 但是,使用Schema也會添加一個_id字段(只要您沒有禁用),並且可能會使用一些更多的資源來跟蹤subdoc。

替代聲明語法

新的V3如果您不需要訪問子文檔模式實例,你也可以通過簡單地傳遞對象字面[聲明子文檔。 ..]

+0

但我嘗試過。爲什麼子文檔數據不存儲在單獨的集合中。它總是存儲在mainDoc集合中。 – 2013-05-27 11:13:53

+16

這就是子文件的工作方式。它們嵌入在文檔中。在玩貓鼬之前,請確保您瞭解底層的MongoDB。 – AndyL 2013-05-31 17:06:00

+1

關於模式添加_id,這是有道理的,但我創建了一個具有一個子文檔數組和一個對象文字數組的模式,並且_id被添加到兩者。行爲改變了嗎? – 2016-05-03 17:12:11

10

我認爲這是由SO上的多個帖子在別處處理的。

幾個:

最大的關鍵是,沒有一個統一的答案在這裏,只有一套相當複雜的權衡。

+1

也許我沒有正確解釋我的問題 - 這不是我應該如何構建數據庫的問題,而是使用子模式的內部結構而不是將數組寫入更深層的問題。我使用subschema的主要原因是我可以使用自定義模式類型並讓它們驗證 - 這與嵌套數組無關(來自之前的問題)。就像我可以告訴一個subdoc幾乎和嵌套數組一樣 - 我只是不知道它的內部 - 如果使用它們會產生性能問題或類似問題。 – cyberwombat 2013-03-04 23:44:43

26

如果你在你的模型中的各個部分被重新使用的模式,那麼它可能是有用的定義各個模式對兒童的文檔,這樣你就不必重複自己。

+2

這是一個很好的答案。有時我會在多個模型中使用子文檔,或者需要區分模型中的兩個字段,但仍然具有相同的子文檔結構。 – 2014-07-09 09:17:02

+1

你還應該考慮保存冗餘信息的好處/缺點。 – 2014-11-24 09:37:34

8

如果這些文檔是靜態文檔或者由於性能影響而不超過幾百個,則應使用嵌入式文檔。我剛纔已經討論過這個問題。最近,作爲MongoDB解決方案架構師的Asya Kamsky寫了一篇關於「使用子文檔」的文章。

我希望這有助於誰在尋找解決方案或最佳實踐。

原始帖子在http://askasya.com/post/largeembeddedarrays。 您可以在https://stackoverflow.com/users/431012/asya-kamsky

首先,找到她的個人資料計算器,我們要考慮我們爲什麼會想要做這樣的事情 。通常,我建議人們嵌入他們在獲取此文檔時始終想要返回的東西。這方面的翻轉 是你不想在文件 中嵌入你不想回頭的東西。

如果嵌入我執行到文檔中的活動,它會在 第一工作的偉大,因爲我所有的活動都是在那裏與一個單一的閱讀 你可以回到你可能想要的一切告訴我:「你最近 點擊這裏,這裏是你的最後兩條評論「但發生了什麼 六個月過去了,我不在乎我做了很長一段時間的事情 以前,你不想讓他們看我,除非我專門去 找一些老的活動?

首先,你將最終返回越來越大的文件,並關注 關於它的越來越小的部分。但是你可以使用投影到 只返回一些數組,真正的痛苦是 磁盤上的文件會變大,它仍然會全部被讀取,即使你只有 會把它的一部分返回到最後用戶,但由於我的活動是 不會停止,只要我活躍,該文件將繼續 增長和增長。

最明顯的問題是最終你會遇到16MB的 文件限制,但這並不是你應該關注的 。隨着文檔不斷增長,每次需要重新定位到磁盤上時都會產生越來越高的成本,並且即使採取 步驟來減輕碎片效應,您的寫入總數也會不必要地太長,從而影響您的整體性能 整個應用程序。

還有一件事你可以完全殺死你的 應用程序的性能,這是索引這個不斷增加的 陣列。這意味着每次重新定位此陣列的文檔 時,需要更新的索引條目的數量與 中索引值的數量成正比,並且數組越大,數組越大該號碼將爲 。

我不希望這從使用數組嚇唬你,當他們是一個很好的 適合數據模型 - 他們是文檔 數據庫的數據模型的一個強大的功能,但像所有強大的工具,它需要在正確的情況下使用 ,應謹慎使用。

+0

這應該是最好的答案;這是錢的問題。 MongoDB自己的白皮書說的幾乎是一回事。 – 2017-09-13 21:22:01

7

基本上,創建一個變量nestedDov,並把它放在這裏name: [nestedDov]

簡單的版本:

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

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

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" 
    ] 
} 

例子:

enter image description here

+0

這並不能解決所有這些問題中的一個問題。 – cyberwombat 2016-09-02 16:34:20

+0

我編輯了一下,以便更有意義。你怎麼看? – 2016-09-02 20:32:19

+1

問題不在於如何做嵌套模式。它討論了Mongoose是否更適合使用嵌套模式或嵌入式子文檔。基本上我們正在談論基準或排序或邊緣情況,其中貓鼬喜歡彼此。正如所選答案提到,它至少從V3開始似乎沒有任何區別。 – cyberwombat 2016-09-02 21:50:58