【问题标题】:mongodb schema design for blogs用于博客的 mongodb 架构设计
【发布时间】:2011-07-10 15:15:44
【问题描述】:

您将如何为具有基于文档的数据库 (mongodb) 的类似博客的网站设计架构。该站点具有以下对象:用户、文章、评论。用户可以在文章中添加评论。每个用户也可以对每个评论进行一次投票。

我希望能够高效地执行这些查询:
1. 获得文章 A、文章 A 的 cmets 和每个 cmets 的票数
2. 获取用户 B 在所有文章中的所有 cmets
3.获取用户B投票给的所有cmets

我的第一次尝试是将文章和 cmets 放在单独的集合中,并且评论可以包含投票给它的用户列表。这使得查询 1 和 2 变得简单。对于 3,我添加了 Vote 集合,用于跟踪用户的投票。

有一些明显的缺点,例如复制用户投票数据,并且查询 1 需要两次调用数据库。有更好的方法吗?

Article {
  "user_id"
}

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

Vote {
    "user_id",
    "comment_id",
}

【问题讨论】:

    标签: database-design mongodb


    【解决方案1】:
    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] },
        ...
      ]
    }
    

    这里的基本前提是我将Comments 嵌套在Article 中。 Votes 仅适用于 Comment,因此它们已存储为每个 Comment 的数组。在这种情况下,我刚刚存储了 user_id。如果要存储更多信息(time_created 等),则可以对对象数组进行投票:

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

    如何高效地执行查询:

    1. 获取文章 A、文章 A 的 cmets 以及每个 cmets 的投票数
    db.articles.find( { _id : 'A' } )
    

    这可以通过一个查询获得所有内容。您可能需要执行一些客户端逻辑来计算每条评论的投票数,但这非常简单。

    1. 获取用户 B 在所有文章中的所有 cmets
    db.articles.ensureIndex( { "comments.user_id" : 1 } )
    db.articles.find( { "comments.user_id" : 987654 } ) // returns all document fields
    

    索引将允许有效地搜索文档中的 cmets。

    目前无法仅从子数组中提取匹配项。该查询实际上将返回该用户的所有带有 cmets 的文章。如果这可能是数据过多,您可以进行一些修剪。

    db.articles.find( { "comments.user_id" : 987654 }, { "title" : 1, "comments.user_id" : 1 })
    
    1. 获取用户 B 投票支持的所有 cmets
    db.articles.ensureIndex( { "comments.votes" : 1 } )
    db.articles.find( { "comments.votes" : 987654 } )
    

    同样,这将返回所有文章,而不仅仅是 cmets。

    这里需要权衡取舍。退回文章可能看起来我们带回了太多数据。但是,当您进行查询 #3 时,您打算向用户显示什么?

    如果没有评论本身,获取“我投票支持的cmets”的列表并不是非常有用。当然,如果没有文章本身(或至少只是标题),评论就不是很有用。

    大多数情况下,查询 #3 会演变为从 VotesCommentsArticles 的连接。如果是这样,那为什么不把文章带回来呢?

    【讨论】:

    • 16MB/文档的限制呢?
    • 如果您担心单个博客文章超过 16MB(那是很多文本),那么您需要进行不同的架构设计。许多博客实际上将其作为单独的查询来获取,因此它们实际上并没有同时访问这两个部分。如果这是您的顾虑,那么您可以选择不同的架构。
    • 我需要一个类似的博客设计,我需要从所有文章中获取按日期排序的 cmets 进行审核。现在这个结果也应该分页。我应该仍然坚持这种架构还是将 cmets 部分放到另一个集合中?
    • 如果您打算将评论与文章分开查询,那么它值得拥有自己的收藏。 MongoDB 中的建模应该围绕“顶级”对象。如果您只打算在文章中查询评论,那么您可以使用上面的模式。如果您打算单独查询评论,那么您需要将它们分开。 (请注意,投票嵌套可能仍然有效
    • 其实我也很担心单个文档的限制。这就是为什么我不敢像上面的架构那样把它们放在一起,而是将它们分成两个文档并建立简单的关系。
    猜你喜欢
    • 2011-10-05
    • 1970-01-01
    • 2016-06-15
    • 2012-08-25
    • 2011-05-25
    • 1970-01-01
    • 2016-02-09
    • 2018-07-04
    相关资源
    最近更新 更多