在其他人之后发布这个答案,所以我将重复提到的一些事情。请接受第一个合适的答案,而不是这个。
也就是说,有一些事情需要考虑。考虑这三个问题:
- 每次查询帖子时都会要求所有评论吗?
- 您想直接查询评论(例如查询特定用户的评论)吗?
- 您的系统使用率会相对较低吗?
如果所有问题都可以用“是”回答,那么您可以嵌入评论数组。在所有其他情况下,您可能需要一个单独的集合来存储您的评论。
首先,您实际上可以以并发安全的方式自动更新和删除注释(请参阅使用位置运算符的更新),但有些事情您不能做,例如基于索引的插入。
对任何类型的大型集合使用嵌入式数组的主要问题是移动更新问题。MongoDB 为每个文档保留一定数量的填充(请参阅 参考资料db.col.stats().paddingFactor
)以允许它根据需要增长。如果它用完了这个填充(它通常会出现在你的用例中),它将不得不在磁盘上移动那个不断增长的文档。这使得更新速度变慢了一个数量级,因此对高带宽服务器来说是一个严重的问题。一个相关但不太重要的问题是带宽。如果您别无选择,只能查询整个帖子及其所有评论,即使您只显示前 10 条,您将浪费相当多的带宽,这在云环境中尤其是一个问题(您可以使用 $切片以避免其中一些)。
如果您确实想嵌入这里是您的基本操作:
添加评论 :
db.posts.update({_id:[POST ID]}, {$push:{comments:{commentId:"remon-923982", author:"Remon", text:"Hi!"}}})
更新评论:
db.posts.update({_id:[POST ID], 'comments.commentId':"remon-923982"}, {$set:{'comments.$.text':"Hello!"}})
删除评论
db.posts.update({_id:[POST ID], 'comments.commentId':"remon-923982"}, {$pull:{comments:{commentId:"remon-923982"}}})
所有这些方法都是并发安全的,因为更新标准是(进程范围的)写锁的一部分。
综上所述,您可能想要一个专门的评论收藏集,但这有第二个选择。您可以将每条评论存储在专用文档中,也可以使用评论桶,例如,每条评论 20-30 条(在此处详细描述http://www.10gen.com/presentations/mongosf2011/schemascale)。这有优点和缺点,所以由你决定哪种方法最适合你想做的事情。如果您每篇文章的评论可能超过几百条,我会选择存储桶,因为您需要分页它们的 skip(N) 游标方法的 o(N) 性能。在所有其他情况下,只需使用每个文档的评论方法。这对于查询其他用例的评论也是最灵活的。