0

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

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

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

我们将最外层的文档称为 ,将调用其中的所有子owner文档,并调用其中的所有子文档。owner.revisionsrevisionrevision.derivativesderivative

我正在寻找特定内部特定内部$addToSetderivatives集合。如果我必须用 Python 编写它,它看起来像这样:revisionowner

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

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

4

1 回答 1

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(因为它会在服务器上两次递增 1。

我猜你的对象也发生了同样的事情——你想要的类似更新操作是$pushoperator

于 2013-10-30T04:04:54.017 回答