【问题标题】:MongoDB + NoRM- Concurrency and collectionsMongoDB + NoRM-并发和集合
【发布时间】:2011-06-30 01:20:40
【问题描述】:

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

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;}
}

如果我们假设多个用户可能会为同一个帖子发布 cmets,那么对它们之间的关系建模的最佳方法是什么?

如果 Post 有一个 cmets 集合,我可能会遇到并发问题,不是吗?

并且在 Comment 上放置类似 FK 的属性似乎过于相关,或者?

【问题讨论】:

    标签: c# mongodb linq norm nosql


    【解决方案1】:

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

    如果您聚合 cmets,您应该 a) 在帖子上实现修订号,允许您检测竞争条件并实现乐观并发的处理,或者 b) 添加带有 MongoDB 修饰符的新 cmets - 例如像

    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 命令加载帖子及其 cmets。

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

    【讨论】:

      【解决方案2】:

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

      为了避免并发问题,MongoDB 提供了几个atomic operations。特别是有几个update modifiers 可以很好地与“子文档”或“子数组”配合使用。

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

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

      【讨论】:

        【解决方案3】:

        他们提供了一个示例,说明您将如何对其建模over on the MongoDB page on inserting - 我认为您希望在您的帖子中将一组 cmets 作为属性公开。您可以将 cmets 添加到给定的 Post 实体,这将消除将 Comment 实体绑定回其父 Post 实体的问题,正如您所质疑的那样,这在 RDBMS 中是有意义的,但在 NoSQL 中则没有那么多解决方案。

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

        【讨论】:

        • 当然,以我目前的知识,我不应该在其上构建应用程序。我试图了解 MongoDB 是否将集合视为一个单一值,或者在检测到并发时它是否合并集合。
        • @Roger Alsing - mongodb.org/display/DOCS/How+does+concurrency+work 稍微深入了一点,但我并不完全确定。从我的阅读方式来看,这听起来隐约像是在引擎盖下有一个信号量,可以让添加一条评论,然后添加第二条评论。
        【解决方案4】:

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

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

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

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

        【讨论】:

        • 你是怎么做到的?您是否提取并更新现有的?您是否使用了原子$push 运算符?你用findAndModify命令了吗?
        猜你喜欢
        • 1970-01-01
        • 2011-07-18
        • 2011-10-02
        • 1970-01-01
        • 2011-09-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多