附加到文档列表中的子文档中的列表?

时间:2013-10-30 03:29:10

标签: mongodb

我在Python中使用MongoEngine来处理我的数据模型。

我有一个基本上看起来像BSON所示的数据模型:

{
   'id': ...
   'revisions': [
       {
          'id': ...
          'revision': 1,
          'derivatives': [
              {
                  'id': ... 
                  'name': 'Derivative 1'
              }
          ]
       }
   ]
}

我们将最外面的文档称为ownerowner.revisions中的所有子文档都将被调用revisionrevision.derivatives中的所有子文档都将被调用derivative }。

我希望$addToSet设置在特定derivatives内特定revision内的owner。如果我必须用Python编写它,它看起来像这样:

def add_to_set(owner_id, revision_id, new_derivative):
    for owner in owner_collection:
       if owner.id == owner_id:
           # found the right owner
           for revision in owner.revisions:
               if revision.id == revision_id:
                   # we've found the right revision in the right owner
                   # now append and get out
                   revision.derivatives.append(new_derivative)
                   return

如何运行此类查询,在右侧revision内选择正确的owner,并在derivatives上以原子方式附加到内部revision集合?< / p>

很难弄清楚如何开始使用这样的更新查询。

1 个答案:

答案 0 :(得分:0)

问题在于使用基于旧版本对象的保存 - 它不是线程安全的。

您希望使用基于匹配条件原子操作对象的update运算符,而不是单方面用全新对象覆盖对象(通过_id)。

不安全的“保存”示例:

线程1:使用字段{_id:1, a:1}读取对象,增加a,保存{_id:1,a:2}
线程2:使用字段{_id:1, a:1}读取对象,递增a,保存{_id:1,a:2}

将此与“安全”更新对比:

线程1:使用运算符{_id:1}更新与{$inc:{a:1}}匹配的对象 线程2:使用运算符{_id:1}

更新与{$inc:{a:1}}匹配的对象

无论两个线程在第二种情况下执行什么顺序,a的值都将为2(因为它将在服务器上增加两次。

我猜你的对象正在发生同样的事情 - 你需要的类似更新操作是$push operator