在MongoDB中查询和排序以获得多对多关系

时间:2015-03-20 14:46:35

标签: mongodb database-design mongodb-query database

假设我在userspostslikes之间存在关系。用户可以喜欢帖子和许多用户都喜欢的帖子。

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

  1. 喜欢帖子的顺序
  2. 按各种post属性过滤和排序 - 例如标题,发布回复的数量,创建帖子的时间等等
  3. 假设帖子数量大约为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查询:[post_ids]。

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

2 个答案:

答案 0 :(得分:1)

我会使用#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中进行更改。这可能不算什么,或者它可能很麻烦,取决于你选择嵌入的内容以及帖子在有很多喜欢之后被修改的频率。

答案 1 :(得分:0)

你的第一个选择对我来说似乎很好。它很好地处理了您的两个要求。 如,

  1. 您需要根据帖子的属性对评论,帖子进行排序,通过汇总进行评论
  2. 您需要根据某些属性过滤文档(帖子)。
  3. 2个集合的缺点是您需要运行2个查询来获取一段数据。 NoSQL数据库使您可以灵活地将相关数据存储在一个位置,并为相同数据提供最佳性能。如果不使用NoSQL的好处,您将无法实现优化的性能。

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