假设我在users
,posts
,likes
之间存在关系。用户可以喜欢帖子和许多用户都喜欢的帖子。
我的目标是能够在MongoDB中设计一个db结构,这样我就可以快速查询用户喜欢的所有帖子,并按照下面列出的多种方式对它们进行排序/过滤(不是同时 - 想一想下拉列表,可让您更改搜索结果的排序顺序)
post
属性过滤和排序 - 例如标题,发布回复的数量,创建帖子的时间等等假设帖子数量大约为100,000,每个帖子的大小为100-1000个
我想到的可能的解决方案:
1)likes
嵌入posts
。
这样可以轻松处理#2,因为您只需要一个超过likes.user_id
的索引以及您需要的任何其他帖子属性。这也很快,因为您只需要运行一个查询。
然而,这使得无法按用户喜欢的东西(AFAIK)进行排序。
2)likes
是一个单独的集合,其属性为post_id
,account_id
。
这样可以轻松处理#1,因为您可以按_id排序。但是,除非你复制&将post
属性缓存到like
文档中,处理#2变得不可能。这是可能的,但实际上并不理想。此外,查询速度较慢。您需要运行两个查询 - 一个用于查询like
集合,然后使用$ in查询post
查询:[post_ids]。
我应该考虑其他任何解决方案/设计吗?我在这些提议的解决方案中遗漏了什么吗?
答案 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)
你的第一个选择对我来说似乎很好。它很好地处理了您的两个要求。 如,
2个集合的缺点是您需要运行2个查询来获取一段数据。 NoSQL数据库使您可以灵活地将相关数据存储在一个位置,并为相同数据提供最佳性能。如果不使用NoSQL的好处,您将无法实现优化的性能。
不要从RDBMS的角度思考(忘记规范化)。如果您需要使用第一个选项进行更多性能优化,请使用索引,分片(使用分片键作为字母范围,地理位置等)