MongoDB + NoRM-并发和集合
假设我们有以下文档结构:
class BlogPost
{
[MongoIdentifier]
public Guid Id{get;set;}
public string Body{get;set;}
....
}
class Comment
{
[MongoIdentifier]
public Guid Id{get;set;}
public string Body {get;set;}
}
如果我们假设多个用户可能对同一篇文章发表评论,那么对它们之间的关系进行建模的最佳方法是什么?
如果 Post 有评论集合,我可能会遇到并发问题,不是吗?
在 Comment 上放置类似 FK 的属性似乎太相关了,或者?
Lets say we have the following document structure:
class BlogPost
{
[MongoIdentifier]
public Guid Id{get;set;}
public string Body{get;set;}
....
}
class Comment
{
[MongoIdentifier]
public Guid Id{get;set;}
public string Body {get;set;}
}
If we assume that multiple users may post comments for the same post, what would be the best way to model the relation between these?
if Post have a collection of comments, I might get concurrency problems, won't I ?
And placing a FK like attribute on Comment seems too relational , or?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您基本上有两个选择:1. 在帖子文档中聚合评论,或 2. 将帖子和评论建模为文档。
如果您聚合评论,您应该a)在帖子上实现修订号,允许您检测竞争条件并实现乐观并发的处理,或者b)使用MongoDB修饰符添加新评论 - 例如类似
如果您对帖子进行建模并将评论作为单独的文档,处理并发可能更容易,但您无法使用单个
findOne
命令加载帖子及其评论。在我看来,(1) 是迄今为止最有趣的选项,因为它将帖子建模为聚合对象,这正是您戴上 OO 眼镜时的样子:)。这绝对是面向文档的方法,而(2)类似于关系数据库的平面结构。
You basically have two options: 1. Aggregate comments in the post document, or 2. Model post and comment as documents.
If you aggregate the comments, you should either a) implement a revision number on the post, allowing you to detect race conditions and implement handling of optimistic concurreny, or b) add new comments with a MongoDB modifier - e.g. something like
If you model post and comment as separate documents, handling concurrency is probably easier, but you lose the ability to load a post and its comments with a single
findOne
command.In my opinion, (1) is by far the most interesting option because it models the post as an aggregate object, which is exactly what it is when you put your OO glasses on :). It's definitely the document-oriented approach, whereas (2) resembles the flat structure of a relational database.
这是典型的 NoSQL 示例之一。执行此操作的标准方法是将
Comments
作为对象数组存储在BlogPost
中。为了避免并发问题,MongoDB 提供了多种原子操作。特别是有几个更新修饰符可以很好地与“子文档”配合使用”或“子数组”。
对于诸如“将此评论添加到帖子中”之类的内容,您通常会使用
$push
命令将评论附加到帖子中。我发现您正在使用“NoRM”驱动程序。看起来他们支持原子命令,正如所证明的那样他们的测试。事实上,他们的测试执行“将此评论推送到博客文章”。
This is one of the canonical NoSQL examples. The standard method for doing this is to store the
Comments
as an array of objects inside of theBlogPost
.To avoid concurrency problems MongoDB provides several atomic operations. In particular there are several update modifiers that work well with "sub-documents" or "sub-arrays".
For something like "add this comment to the post", you would typically use the
$push
command which will append the comment to the Post.I see that you're using the "NoRM" drivers. It looks like they have support for atomic commands, as evidenced by their tests. In fact, their tests perform a "push this comment to the blog post".
他们给出了一个示例,说明如何在插入时在 MongoDB 页面上进行建模 - 我认为您希望将评论集合作为您帖子的属性公开。您可以向给定的 Post 实体添加注释,这样就无需将 Comment 实体绑定回其父 Post 实体,正如您所质疑的那样,这在 RDBMS 中有意义,但在 NoSQL 中则没有那么多意义解决方案。
就并发性而言,如果您不信任 Mongo 会为您处理该问题,那么这可能是一个很大的暗示,表明您不应该在其之上构建应用程序。
They sort of give an example of how you'd model it over on the MongoDB page on inserting - I think you'd want a collection of comments exposed as a property on your post. You'd add comments to a given Post entity and this would do away with tying a Comment entity back to its parent Post entity which, as you are right to question, is something that makes sense in a RDBMS but not so much in a NoSQL solution.
As far as concurrency goes, if you don't trust Mongo to handle that for you, it's probably a big hint that you shouldn't be building an application on top of it.
我创建了一个测试应用程序,它生成 1000 个并发线程,将“评论”添加到同一个“帖子”中,结果是大量评论丢失。
因此 MongoDB 将子集合视为单个值,默认情况下不合并更改。
如果我在帖子上有一个 Comments 集合,那么当两个或多个用户同时添加评论时(不太可能但可能),我会遇到并发问题。
那么是否可以在不更新整个内容的情况下向 post.comments 集合添加评论发布对象?
I've created a test app that spawns 1000 concurrent threads adding "Comments" to the same "Post", the result is that alot of comments are lost.
So MongoDB treats child collections as a single value, it does not merge changes by default.
If I have a Comments collection on post, then I get concurrency problems when two or more users are adding comments at the exact same time (unlikely but possible)
So is it possible to add a comment to the post.comments collection without updating the entire post object?