有效地修改子文档

时间:2014-12-22 12:04:10

标签: mongodb mongodb-query

我有以下文件:

{
  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 } }

如何以原子方式和最少量的查询应用上述所有更改?

1 个答案:

答案 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});