2011-03-07 86 views
26

您將如何使用基於文檔的數據庫(mongodb)爲類似博客的網站設計模式。該網站包含以下對象:用戶,文章,評論。用戶可以將評論添加到文章。每個用戶也可以在每條評論中投票一次。針對博客的mongodb模式設計

我希望能夠做到有效地這些查詢:每評論
2.
1. GET A條,評論新的文章,和#票的所有文章
3獲得由用戶B的所有意見。獲取所有評論用戶B投了贊成

我的第一個嘗試是把文章和評論放在單獨的收藏和評論可以包含投票的用戶列表。這使查詢1和2變得簡單。 3,我添加了投票收集,保持用戶的投票跟蹤。

有一些明顯的缺點,如複製用戶投票數據和查詢1將採取兩個調用數據庫。有更好的方法嗎?

Article { 
    "user_id" 
} 

Comment { 
    "user_id", 
    "article_id", 
    [user_voted], 
} 

Vote { 
    "user_id", 
    "comment_id", 
} 

回答

28
Article { 
    "_id" : "A", 
    "title" : "Hello World", 
    "user_id" : 12345, 
    "text" : 'My test article', 

    "comments" : [ 
    { 'text' : 'blah', 'user_id' : 654321, 'votes' : [987654]}, 
    { 'text' : 'foo', 'user_id' : 987654, 'votes' : [12345, 654321] }, 
    ... 
    ] 
} 

這裏的基本前提是,我已經嵌套在CommentsArticle內。 Votes僅適用於Comment,因此它們已被存儲爲每個Comment的陣列。在這種情況下,我剛剛存儲了user_id。如果你想存儲更多的信息(TIME_CREATED等),那麼你可以投票對象的數組:

... 'votes' : [ { user_id : 987654, ts : 78946513 } ] ... 

如何執行你的查詢效率:

  1. 獲得A條評論每評論
db.articles.find({ _id : 'A' }) 

這得到第一個和#票一切都有一個查詢。您可能必須執行一些客戶端邏輯來對每條評論的投票數進行計數,但這非常簡單。

  1. 得到用戶B所有評論所有文章
db.articles.ensureIndex({ "comments.user_id" : 1 }) 
db.articles.find({ "comments.user_id" : 987654 }) // returns all document fields 

該指數將允許有效地搜索文檔中的註釋。

目前沒有辦法只從子數組中提取匹配。該查詢實際上將返回所有包含該用戶評論的文章。如果這可能是太多的數據,你可以做一些修整。

db.articles.find({ "comments.user_id" : 987654 }, { "title" : 1, "comments.user_id" : 1 }) 
  1. 讓所有評論用戶B投票贊成
db.articles.ensureIndex({ "comments.votes" : 1 }) 
db.articles.find({ "comments.votes" : 987654 }) 

同樣,這將返回所有的文章,不只是評論。

這裏有一個折衷。返回文章可能看起來像我們正在帶回太多的數據。但是,當您進行查詢#3時,您計劃向用戶展示什麼?

獲取的評論「我已投票評論」沒有評論本身並不是非常有用。如果沒有文章本身(或者至少只是標題),評論當然不是很有用。

大多數情況下,查詢#3分配從VotesCommentsArticles的連接。如果是這樣的話,那麼爲什麼不把條款帶回來呢?

+3

那麼16MB /文件的限制呢? – 2014-01-29 00:43:13

+0

如果您擔心有一篇博文超過16MB(_that是很多text_),那麼您需要製作一個不同的模式設計。許多博客實際上將其作爲單獨的查詢來源,因此他們實際上不會同時訪問這兩個作品。如果這是你的擔心,那麼你選擇一個不同的模式。 – 2014-01-29 02:49:24

+0

我需要一個類似的博客設計,我需要從所有文章中按照日期排序來評論評論。現在這個結果也應該分頁。我是否應該堅持這種架構或將評論部分放到另一個集合中? – 2014-07-14 17:11:56