我有以下文件:
{
A1: 1,
A2: 2,
A3: [
{ test: "B1", value: 3 },
{ test: "B2", value: 4 }
]
}
我想将文档更新为:
{
A1: 10, // "A1" becomes 10
A2: 2, // "A2" remains unchanged
A3: [
{ test: "B1", value: 30 }, // "value" becomes 30 where "test" is "B1"
{ test: "B2", value: 4 }, // "value" remains unchanged where "test" is "B2"
{ test: "B3", value: 50 } // a new sub-document is added
],
A4: 60 // "A4" is added with the value of 60
}
如果我没有子文档数组,并且我只需要更改A*
值,我可以简单地使用$set
,这将设置值{ A1
并添加A4
:
{ $set: { A1: 10, A4: 60 } }
如何以原子方式和最少量的查询应用上述所有更改?
答案 0 :(得分:0)
我最初只尝试使用一个查询来更新文档,但看起来您无法在同一查询中的任何给定数组上运行两个操作。这是我得到的错误:
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 16837,
"errmsg" : "Cannot update 'A3.0.value' and 'A3' at the same time
"
}
})
然后我决定将该查询分成两部分,并设法获得所需的功能。
在第一个查询中,我在B1
数组中搜索了具有测试值A3
的对象的所有文档,并将该特定对象的值设置为30。
此外,由于A1
的值默认情况下会更改,因此我更新了其值并添加了A4
,因为它是一个新元素。
然后我指定了multi
参数,以便更新符合条件的所有文件
db.collection.update({ A3: { $elemMatch: { test: "B1"} } },
{ $set: { "A3.$.value": 30, A1: 10, A4: 60 }},
{ multi: true});
在第二个查询中,我搜索了所有具有现有A3
数组的文档并推送了新对象。
db.collection.update({ A3: { $exists: true }},
{ $push: { A3: { test: "B3", value: 50 }}},
{ multi: true});