MongoDB + NoRM-并发和集合

时间:2011-02-18 19:18:20

标签: c# mongodb linq norm nosql

假设我们有以下文档结构:

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 like属性似乎太关系了,或者?

4 个答案:

答案 0 :(得分:4)

您基本上有两种选择:1。在帖子文档中汇总评论,或2.模拟帖子和评论作为文档。

如果您聚合评论,您应该a)在帖子上实现修订号,允许您检测竞争条件并实施乐观concurreny的处理,或b)使用MongoDB修饰符添加新评论 - 例如

之类的东西
var posts = mongo.GetCollection<Post>();
var crit = new { Id = postId };
var mod = new { Comments = M.Push(new Comment(...)) };

posts.Update(crit, mod, false, false);

如果您将帖子和评论建模为单独的文档,处理并发可能会更容易,但您无法使用单个findOne命令加载帖子及其评论。

在我看来,(1)是迄今为止最有趣的选项,因为它将帖子建模为聚合对象,这正是你将OO眼镜放在:)上的原因。它绝对是面向文档的方法,而(2)类似于关系数据库的扁平结构。

答案 1 :(得分:2)

这是规范的NoSQL示例之一。执行此操作的标准方法是将Comments存储为BlogPost内的对象数组。

为了避免并发问题,MongoDB提供了几个atomic operations。特别是有几个update modifiers适用于“子文档”或“子数组”。

对于“将此评论添加到帖子”,您通常会使用$push命令将评论附加到帖子。

我看到你正在使用“NoRM”驱动程序。看起来他们支持原子命令,证明by their tests。事实上,他们的测试执行“将此评论推送到博客帖子”

答案 2 :(得分:0)

他们给出了一个如何对其进行建模的示例over on the MongoDB page on inserting - 我认为您希望在帖子中将一系列评论作为属性公开。你会给一个给定的Post实体添加注释,这会消除将一个Comment实体绑定回它的父Post实体,正如你提出的那样,这个实体在RDBMS中是有意义的,但在NoSQL中却没有那么多溶液

就并发而言,如果你不相信Mongo为你处理这个问题,那么你可能不应该在它上面构建一个应用程序。

答案 3 :(得分:0)

我创建了一个测试应用程序,它产生了1000个并发线程,将“注释”添加到同一个“帖子”中,结果是很多评论都丢失了。

因此,MongoDB将子集合视为单个值,默认情况下不会合并更改。

如果我在帖子上有一个评论集合,那么当两个或更多用户在同一时间添加评论时,我会遇到并发问题(不太可能,但可能)

那么可以在不更新整个帖子对象的情况下向post.comments集合添加评论吗?