【问题标题】:Query and Sort in MongoDB for a many-to-many relationship在 MongoDB 中查询和排序以实现多对多关系
【发布时间】:2015-05-24 00:38:04
【问题描述】:

假设我在userspostslikes 之间有关系。一个用户可以点赞一个帖子,一个帖子可以被很多用户点赞。

我的目标是能够在 MongoDB 中设计一个数据库结构,以便我可以快速查询用户喜欢的所有帖子,并以下面列出的多种方式对它们进行排序/过滤(不是同时 - 想想下拉菜单,可让您更改搜索结果的排序顺序)

  1. 帖子被点赞的顺序
  2. 按各种post 属性过滤和排序 - 例如标题、帖子回复数、帖子创建时间等

假设帖子的数量在 100,000 左右,每个帖子的点赞量在 100-1000 左右

我想到的可能解决方案:

1) likes 嵌入在 posts 中。

这使得 #2 可以轻松处理,因为您只需在likes.user_id 和您需要的任何其他帖子属性上都有一个索引。这也很快,因为您只需要运行一个查询。

但是,这使得无法按用户喜欢某物的时间进行排序 (AFAIK)。

2) likes 是具有post_idaccount_id 属性的单独集合。

这使得 #1 可以轻松处理,因为您可以按 _id 排序。但是,除非您将post 属性复制并缓存到like 文档中,否则无法处理#2。这是可能的,但实际上并不理想。此外,查询速度较慢。您需要运行两个查询 - 一个查询 like 集合,然后使用 $in: [post_ids] 查询 post

还有其他我应该考虑的解决方案/设计吗?我在这些建议的解决方案中遗漏了什么吗?

【问题讨论】:

  • 非规范化。对于 NoSQL,通常的做法是在多个地方拥有一条信息。因此,例如,您可以结合这两种解决方案,并在单独的表格中嵌入喜欢。

标签: mongodb database-design mongodb-query database


【解决方案1】:

您的第一个选项对我来说似乎相当不错。它很好地处理了您的两个要求。 作为,

  1. 您需要根据帖子的属性对 cme​​ts、posts、comment 进行排序,这可以通过聚合来实现
  2. 您需要根据一些属性过滤文档(帖子),这也是可能的。

2 个集合的缺点是您需要运行 2 个查询才能获取一条数据。 NoSQL 数据库让您可以灵活地将相关数据存储在一个地方,并提供最佳性能。如果不使用 NoSQL 的优势,您将无法获得优化的性能。

不要从 RDBMS 的角度思考(忘记规范化)。如果您需要使用第一个选项进行更多性能优化,请使用索引、分片(将分片键作为字母范围、地理等)

【讨论】:

  • #1 不允许您按帖子被点赞的顺序排序。嵌入式数组具有架构:like: {account_id: ObjectId, time: Date}。如果您需要某个 account_id 的所有帖子按该帐户喜欢的顺序排列,这是不可能的。
  • 你听说过放松吗?在我看来,这将使 #1 成为可能。
  • 效率不高?你必须每次都放松一下。
  • 您有 2 个选择,1. 性能 2. 易于存储数据。一般来说,NoSQL 是为方便而设计的,即将相关数据存储在一起。性能可以通过高效的查询、索引、分片来实现。将相关数据存储在 2 个不同的集合中是没有意义的,您需要像连接一样查询这两个集合。 (那你为什么不使用 RDBMS 而不是这个)
  • 我不会推荐这个选项 - #2 很困难,需要一个非常低效的聚合查询,就像 OP 所说的那样使用展开。
【解决方案2】:

我会使用 #2 的非规范化版本。有一个like 文件:

{
    "_id" : ObjectId(...),
    "account_id" : 1234,
    "post_id" : 4321,
    "ts" : ISODate(...),
    // additional info about post needed for basic display
    "post_title" : "The 10 Worst-Kept Secrets of Cheesemongers"
    // etc.
}

使用{ "account_id" : 1, "ts" : 1 } 上的索引,您可以有效地找到按相似时间排序的特定用户的like 文档。

db.likes.find({ "account_id" : 1234 }).sort({ "ts" : -1 })

如果您将有关帖子的基本信息放入like 文档中,则无需检索帖子文档,直到用户单击要显示整个帖子的链接。

权衡是,如果有关帖子的某些like 嵌入信息发生更改,则需要在每个like 中更改。这可能没什么,也可能很麻烦,具体取决于您选择嵌入的内容以及帖子在获得大量赞后修改的频率。

【讨论】:

  • 这似乎是一个不错的解决方案,但是如果更新帖子数据呢?更新每个赞的效率如何?这会是批量更新 mongo 功能吗?
猜你喜欢
  • 1970-01-01
  • 2022-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多