我有哪些元素可以简化为这样一个集合:
{tags : [1, 5, 8]}
那里将是阵列的至少一个元件和所有的人都应该是不同的。 我想替换一个标签为另一个,我认为不会有问题。 于是我想出了以下查询:
db.colll.update({
tags : 1
},{
$pull: { tags: 1 },
$addToSet: { tags: 2 }
}, {
multi: true
})
酷,所以它会发现其中有一个我不需要(1),将其删除,并添加一个标签的所有元素另一个(2)如果不存在的话。 问题是,我得到一个错误:
“无法更新‘标签’和‘标签’在同一时间”
这基本上意味着,我不能在同一时间做拉和addtoset。 是否有其他方法可以让我做到这一点?
当然,我可以记住元素的所有ID,然后删除标签,并添加单独的查询,但这并不听起来不错。
该错误是相当多的是什么意思,你不能在相同的更新操作相同的“路径”的两件事情采取行动。 您正在使用的两个运营商,你可能会认为他们不按顺序处理。
您可以为“连续”,你可以可能与获得这样做“批量”操作的API “批量”更新的或其他形式,虽然。 在合理范围内,当然,也反向:
var bulk = db.coll.initializeOrderedBulkOp();
bulk.find({ "tags": 1 }).updateOne({ "$addToSet": { "tags": 2 } });
bulk.find({ "tags": 1 }).updateOne({ "$pull": { "tags": 1 } });
bulk.execute();
不能保证什么都没尝试修改,但它是接近你现在会得到。
还看到原始的“更新”命令与多个文档。
如果要删除,并在同一时间加入,您可能会建模一个“地图”,而不是“设置”。 如果是这样,一个对象可能比阵列工作较少。
代替数据为阵列的:
{ _id: 'myobjectwithdata',
data: [{ id: 'data1', important: 'stuff'},
{ id: 'data2', important: 'more'}]
}
使用数据作为一个对象:
{ _id: 'myobjectwithdata',
data: { data1: { important: 'stuff'},
data2: { important: 'more'} }
}
一命令更新则是:
db.coll.update(
'myobjectwithdata',
{ $set: { 'data.data1': { important: 'treasure' } }
);
硬脑这个答案做的工作在这里和这里 。