博客的 mongodb 架构设计
您将如何为具有基于文档的数据库 (mongodb) 的类似博客的网站设计架构。该站点具有以下对象:用户、文章、评论。用户可以向文章添加评论。每个用户还可以为每个评论投票一次。
我希望能够有效地执行这些查询:
1. 获取文章 A、文章 A 的评论以及每个评论的投票数
2. 获取用户B对所有文章的所有评论
3.获取用户B投票的所有评论
我的第一个尝试是将文章和评论放在单独的集合中,并且评论可以包含投票的用户列表。这使得查询 1 和 2 变得简单。对于 3,我添加了投票收集,用于跟踪用户的投票。
有一些明显的缺点,例如重复用户投票数据,并且查询 1 将需要两次调用数据库。有更好的方法吗?
Article {
"user_id"
}
Comment {
"user_id",
"article_id",
[user_voted],
}
Vote {
"user_id",
"comment_id",
}
How would you design the schema for a blog-like site with document-based databases (mongodb). The site has the following objects: User, Article, Comment. User can add Comments to Article. Each User can also vote exactly once per Comment.
I want to be able to do these queries efficiently:
1. get Article A, comments on Article A and # of votes per comments
2. get all comments by User B across all articles
3. get all comments User B voted for
My first attempt is to put articles and comments in separate collections and comment can contain a list of users that voted for it. This makes query 1 and 2 simple. And for 3, I added Vote collection which keep tracks of votes by users.
There's some obvious drawback such as duplicating user vote data and query 1 will take two calls to the database. Is there a better approach?
Article {
"user_id"
}
Comment {
"user_id",
"article_id",
[user_voted],
}
Vote {
"user_id",
"comment_id",
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里的基本前提是我将
Comments
嵌套在Article
中。投票
仅适用于评论
,因此它们已与每个评论
一起存储为数组。在本例中,我刚刚存储了 user_id。如果您想存储更多信息(time_created 等),那么您可以对对象数组进行投票:如何有效地执行查询:
这只需一个查询即可获取所有内容。您可能需要执行一些客户端逻辑来计算每个评论的投票数,但这非常简单。
该索引将允许有效地搜索文档中的评论。
目前无法仅从子数组中提取匹配项。该查询实际上将返回带有该用户评论的所有文章。如果这可能是太多数据,您可以进行一些修剪。
再次强调,这将返回所有文章,而不仅仅是评论。
这里需要做出权衡。返回文章可能看起来我们带回了太多数据。但是,当您进行查询 #3 时,您打算向用户显示什么?
如果没有评论本身,获取“我投票的评论”列表并不是很有用。当然,如果没有文章本身(或者至少只有标题),评论就不是很有用。
大多数时候,查询 #3 会转化为从
Votes
到Comments
再到Articles
的联接。既然如此,那为什么不直接把文章带回来呢?The basic premise here is that I've nested the
Comments
inside of theArticle
. TheVotes
only apply to aComment
, so they've been stored as an array with eachComment
. In this case, I've just stored the user_id. If you want to store more information (time_created, etc.), then you can votes an array of objects:How to perform your queries efficiently:
This gets everything with one query. You may have to do some client-side logic to count votes per comment, but this is pretty trivial.
The index will allow for efficiently searching the comments within a document.
There's currently no way to extract only the matches from a sub-array. This query will in fact return all of the articles with comments by that user. If this is potentially way too much data, you can do some trimming.
Again, this will return all of the Articles, not just the comments.
There's a trade-off to be made here. Returning the article may seem like we're bringing back too much data. But what are you planning to display to the user when you make query #3?
Getting a list of "comments I've voted for" is not terribly useful without the comment itself. Of course the comment is not very useful without the article itself (or at least just the title).
Most of the time, query #3 devolves into a join from
Votes
toComments
toArticles
. If that's the case, then why not just bring back the Articles to start with?