MongoDB在数组的子文档中进行upsert并返回更新的子文档

时间:2016-12-08 12:18:16

标签: mongodb

假设我有一个这样的文件:

{ 
     "_id" : ObjectId(1234),
     "name": "foo", 
     "bars": [ 
         { "name": "n1", "myBool": true }, 
         { "name": "n2", "myBool": false }, 
         { "name": "n3", "myBool": false }
     ] 
}

我想找到name(或整个子文档,它并不重要)并将myBool更改为true以获取{{1}中的第一个子文档对于原子操作中给定的bars,当前为false。例如,根据上述数据,我想在_id等于{{n2的文档中返回myBool并将true设为n2 _id 1}}。

我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:2)

使用参数new set为true运行 findAndModify 命令,从而返回修改后的文档而不是原始文档。

更新应使用$ positional operator标识数组中的元素进行更新,而不显式指定数组中元素的位置。为此,数组字段必须作为查询文档的一部分出现。

输出文档有一个value字段,其中包含命令的返回文档:

var result = db.runCommand({
    "findAndModify": "collection",
    "query": { 
        "_id" : 1234, 
        "bars.myBool": false 
    },
    "update": { "$set": { "bars.$.myBool": true } },
    "new": true
});
printjson(result.value);

示例输出

{
    "_id" : 1234,
    "name" : "foo",
    "bars" : [
        {
            "name" : "n1",
            "myBool" : true
        },
        {
            "name" : "n2",
            "myBool" : true
        },
        {
            "name" : "n3",
            "myBool" : false
        }
    ]
}

答案 1 :(得分:0)

<强>更新 可能这是一个解决方案,但满足您的要求,使用以下查询

db.test.findAndModify({
    query: { "_id": 123456, "bars.myBool": false},
    update: {$set: {"bars.$.myBool": true}},
        fields: {
            "bars": {$elemMatch: {"myBool" : false }}
        }   
})

hack是它返回将要修改的原始文档。

返回

{
    "_id" : 123456,
    "bars" : [
        {
            "name" : "n2",
            "myBool" : false
        }
    ]
}

您可以获取正在更新的文档

所以result包含带有单个子文档的数组,您可以通过它获取名称。

详细了解findAndModify