2009-12-05 175 views
7

在MongoDB中存儲嵌套集(如註釋樹)的最佳實踐是什麼?MongoDB嵌套集

我的意思是,每個評論可以有一個家長評論和兒童評論(答案)。

存儲他們這樣的:

{ 
    title: "Hello", 
    body: "Please comment me!", 
    comments: [ 
     { 
      author: "Peter", 
      text: "Hi there", 
      answers: [ 
        { 
         author: "Peter", 
         text: "Hi there", 
         answers: [ 
           { author: "Ivan", text: "Hi there" }, 
           { author: "Nicholas", text: "Hi there" } 
         ] 
        }, 
        { author: "Ivan", text: "Hi there" }, 
        { author: "Nicholas", text: "Hi there" }, 
      ] 
     }, 
     { author: "Ivan", text: "Hi there" }, 
     { author: "Nicholas", text: "Hi there" }, 
    ] 
} 

是不冷靜,因爲我們不能,例如,索要無地圖「它是由彼得·評論所有文章」 /減少。

回答

3

我認爲沒有完美的解決方案 - 取決於哪些操作對您的應用程序更重要。例如,我相信Silicon Alley Insider存儲與MongoDB嵌套的評論。這確實會讓你提到的查詢更難。

一個選項是在頂層存儲數組中所有評論者的列表。把它看作非規範化的數據。然後可以很容易地找到涉及某個評論者的所有帖子。然後深入研究,您可以使用map/reduce或db.eval()來獲取嵌套的發佈信息。另一個注意事項 - 如果你正在處理單個文檔,db.eval()可能比map/reduce更輕。 $哪裏也是一個選項,但速度可能會很慢,所以我喜歡上面提到的額外'評論者列表' - 也不容易索引該列表(請參閱文檔中的'多鍵')。

參見: http://groups.google.com/group/mongodb-user/browse_thread/thread/df8250573c91f75a/e880d9c57e343b52?lnk=gst&q=trees#e880d9c57e343b52

2

在從DM的帖子德懷特·梅里曼鏈接提及使用路徑密鑰,做正則表達式匹配

{ 
    path : "a.b.c.d.e.f" 
} 

另一種方式做,這將與陣列

{ 
    path : ["a", "b", "c", "d", "e", "f"] 
} 

db.test.ensureIndex({path: 1}) 

應該讓它變得非常快。

如果每個節點只能在單一路徑,那麼你就不需要做一下它位於列表

db.test.find({path: "a"}) 

擔心會找到的「一」

所有兒童我可能會使用節點的_id,而不是路徑名。

更新

  • 一件事要小心的是,指數只能在它一個陣列。
  • 小心使用說明您的查詢

    db.test。找到({路徑:{$中: 「A」, 「B」]})

給你

db.test.find({path: {$in: ["a", "b"]}}).explain() 
{ 
     "cursor" : "BtreeCursor path_1 multi", 
     "nscanned" : 2, 
     "nscannedObjects" : 2, 
     "n" : 1, 
     "millis" : 0, 
     "nYields" : 0, 
     "nChunkSkips" : 0, 
     "isMultiKey" : true, 
     "indexOnly" : false, 
     "indexBounds" : { 
       "path" : [ 
         [ 
           "a", 
           "a" 
         ], 
         [ 
           "b", 
           "b" 
         ] 
       ] 
     } 
} 

db.test.find({path: {$all: ["a", "b"]}}).explain() 
{ 
     "cursor" : "BtreeCursor path_1", 
     "nscanned" : 1, 
     "nscannedObjects" : 1, 
     "n" : 1, 
     "millis" : 0, 
     "nYields" : 0, 
     "nChunkSkips" : 0, 
     "isMultiKey" : true, 
     "indexOnly" : false, 
     "indexBounds" : { 
       "path" : [ 
         [ 
           "a", 
           "a" 
         ] 
       ] 
     } 
} 

只使用第一個元素,然後掃描b的所有匹配結果。
如果a是您的根元素或者在您的大部分記錄中,那麼您將對記錄進行幾乎完整的掃描而不是有效的索引查詢。