1

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

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

4

4 回答 4

4

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

如果您汇总评论,您应该 a)在帖子上实现修订号,允许您检测竞争条件并实现乐观并发的处理,或者 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) 类似于关系数据库的平面结构。

于 2011-02-18T20:18:14.460 回答
2

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

为了避免并发问题,MongoDB 提供了几个原子操作。特别是有几个更新修饰符可以很好地与“子文档”或“子数组”配合使用。

对于诸如“将此评论添加到帖子”之类的内容,您通常会使用$push将评论附加到帖子的命令。

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".

于 2011-02-18T20:57:55.143 回答
0

他们提供了一个示例,说明您如何在 MongoDB 页面上对插入进行建模- 我认为您希望将一组评论作为属性公开在您的帖子中。您可以将评论添加到给定的 Post 实体,这将消除将评论实体绑定回其父 Post 实体的问题,正如您所质疑的那样,这在 RDBMS 中是有意义的,但在 NoSQL 中则不那么重要解决方案。

就并发而言,如果您不相信 Mongo 会为您处理,这可能是一个很大的暗示,您不应该在它之上构建应用程序。

于 2011-02-18T19:26:16.777 回答
0

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

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

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

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

于 2011-02-18T19:54:22.707 回答