【问题标题】:Mongo DB Schema DesignMongodb 架构设计
【发布时间】:2014-10-30 14:15:37
【问题描述】:

我正在努力为应用寻找最佳的数据库设计。我有 SQL 背景,倾向于创建或多或少非规范化的数据库设计。

我有以下问题。我有一个包含大约 2000 篇文章的“文章”集合。每篇文章都有相当多的信息。实施推荐系统,我想为每个“文章”与每个“用户”关联一个“PredictedRating”。 在 SQL 中,我将使用三个表对此进行建模:“Articles”、“Users”、“UserToArticle”。 查询应如下所示:我想为每个“文章”关联当前登录用户的“PredictedRating”。在 SQL 中,我将在“文章”和“用户”上进行连接,预先选择相应的用户。 拥有正确的索引是非常快的。

我怎样才能以 mongo 的方式实现呢?当我以所描述的方式实现这一点时,我不得不为每篇文章放置一个 findOne() 查询,这非常低效且缓慢(即使使用索引也是如此)。

你有什么想法吗?重要的是,仅发布当前用户的预测评分。

【问题讨论】:

  • 不清楚你需要什么样的查询。例如,一位用户的所有评分或一篇文章的所有评分或两者兼而有之?
  • 好点:我需要一个用户的所有评分。

标签: mongodb database-schema


【解决方案1】:

经验法则

MongoDB 博客有一些 good advice on data modeling:

  1. 尽可能使用嵌入文档。
  2. 如果子文档经常单独阅读,最好不要嵌入它。
  3. 保持数组小。如果嵌入的文档数组不断增长,请将其替换为引用 id 数组。如果引用数组不断增长,请尝试反转引用或将引用提取到它自己的集合中。
  4. 应用程序级连接仍然是一个选项。正确使用索引和投影时,性能不会下降。
  5. 您可以嵌入很少更新但经常阅读的文档,即使这意味着冗余数据。如果您需要频繁更新,请勿嵌入冗余数据,因为它可能会超过读取优势。
  6. 为您的应用程序优化数据模型。需要一起读取或写入的内容应该移近一些(放入更少的集合中)。

因此,对文档数据库进行建模不像对关系数据模型进行规范化那样简单。当你掌握了这些经验法则后,你应该阅读about data models in the MongoDB manual


示例

我们需要将三个域对象放入 MongoDB:userarticlepredicted rating。我假设有很多用户,甚至更多的文章。很明显,我们不应该将用户和文章放在一个集合中(第 2、4 和 5 条)。因此,我们只需要决定将预测评分放在哪里。

将评分嵌入到文章中

由于您的用例是获取用户的所有预测评分,因此将它们放入文章中会适得其反 (6)。您需要搜索所有文章才能获得评级。除此之外,如果您删除用户,您需要更新每篇文章。

将评分嵌入用户

将评分嵌入用户的好处是您只需一次查询即可获取用户和评分数据。但是您可能希望为每个用户添加每篇文章的评分,因此数组将增长到很多 (3)。

将评分放入自己的收藏中

因此,将评分放入他们自己的集合中是可行的。

{
    _id: ObjectId("f01..."),
    userId: ObjectId("123..."),
    articleId: ObjectId("abc..."),
    predictedRating: 5.4
}

如前所述,这取决于您的数量结构。如果您只有很少的用户或文章很少,嵌入预测评分可能是一种更简单、更快捷的解决方案。

【讨论】:

    猜你喜欢
    • 2012-08-25
    • 2011-05-25
    • 2018-07-04
    • 2011-11-20
    • 2015-04-21
    • 2011-12-28
    • 1970-01-01
    • 2014-02-04
    相关资源
    最近更新 更多