在 MongoDB 中查询和排序 many-to-many 关系

Query and Sort in MongoDB for a many-to-many relationship

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

我的目标是能够在 MongoDB 中设计一个数据库结构,这样我就可以快速查询用户喜欢的所有 post 并且 sort/filter 它们在多个下面列出的方式(不同时 - 考虑一个下拉菜单,让您更改搜索结果的排序顺序)

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

假设 post 的数量是 100,000 的数量级,每个 post 将有大约 100-1000 个赞

我想到的可能的解决方案:

1) likes 嵌入在 posts 中。

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

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

2) likes 是一个单独的 collection,具有属性 post_idaccount_id.

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

还有其他 solutions/designs 我应该考虑的吗?我是否遗漏了这些建议的解决方案中的任何内容?

我觉得你的第一个选项很好。它很好地处理了您的两个要求。 作为,

  1. 您需要根据 post 的属性对评论 post 进行排序,评论可以通过聚合
  2. 您需要根据某些属性过滤文档(posts),这也是可能的。

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

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

我会使用#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 })

如果将 post 的基本信息放入 like 文档中,则无需检索 post 文档,直到用户单击某个link 显示整个 post。

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