我在Python中使用MongoEngine来处理我的数据模型。
我有一个基本上看起来像BSON所示的数据模型:
{
'id': ...
'revisions': [
{
'id': ...
'revision': 1,
'derivatives': [
{
'id': ...
'name': 'Derivative 1'
}
]
}
]
}
我们将最外面的文档称为owner
,owner.revisions
中的所有子文档都将被调用revision
,revision.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>
很难弄清楚如何开始使用这样的更新查询。
答案 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。