Mongodb Update / Upsert数组完全匹配

时间:2014-12-13 14:48:33

标签: mongodb mongodb-query

我有一个集合:

gStats : {
     "_id" : "id1",
     "criteria" : ["key1":"value1", "key2":"value2"],
     "groups" : [
             {"id":"XXXX", "visited":100, "liked":200},
             {"id":"YYYY", "visited":30, "liked":400}
     ]
}

我希望能够更新给定数组标准(完全匹配)的stats数组文档。

我尝试在两个步骤中执行此操作:

从给定“id”的数组中拉出stat文档:

db.gStats.update({
    "criteria" : {$size : 2},
    "criteria" : {$all : [{"key1" : "2096955"},{"value1" : "2015610"}]}
},
{
    $pull : {groups : {"id" : "XXXX"}}
}
)

推送新文件

db.gStats.findAndModify({
    query : {
        "criteria" : {$size : 2},
        "criteria" : {$all : [{"key1" : "2015610"}, {"key2" : "2096955"}]}
    },
    update : {
        $push : {groups : {"id" : "XXXX", "visited" : 29, "liked" : 144}}
    },
    upsert : true
})

Pull查询工作完美。 Push查询会出错:

2014-12-13T15:12:58.571+0100 findAndModifyFailed failed: {
        "value" : null,
        "errmsg" : "exception: Cannot create base during insert of update. Cause
d by :ConflictingUpdateOperators Cannot update 'criteria' and 'criteria' at the
same time",
        "code" : 12,
        "ok" : 0
} at src/mongo/shell/collection.js:614

1 个答案:

答案 0 :(得分:1)

这两个查询都没有实际工作。除非在运营商和$and下,否则您不能多次使用“条件”等关键名称。您还指定了不同的字段(即组)和查询示例文档中不存在的元素。

很难说出你真正想做的事情。但错误主要是由我提到的第一个问题造成的,还有一些额外的问题。所以你的{ "$size": 2 }条件实际上被忽略了,只有第二个条件被应用了。

有效的查询表单应如下所示:

query: {
    "$and": [
        { "criteria" : { "$size" : 2 } },
        { "criteria" : { "$all": [{ "key1": "2015610" }, { "key2": "2096955" }] } }
    ]
}

由于$and提供的数组中指定了每组条件,因此查询的文档结构有效,并且没有覆盖另一个的哈希键名称。这是编写两个条件的正确方法,但是由于这些条件与文档不匹配,因此有一个技巧可以使“upsert”失败。当我们尝试在创建时应用$all参数时,我们需要覆盖正在发生的事情:

update: {
    "$setOnInsert": {
        "criteria" : [{ "key1": "2015610" }, { "key2": "2096955" }]
    },
    "$push": { "stats": { "id": "XXXX", "visited": 29, "liked": 144 } }
}

使用$setOnInsert,以便在应用“upsert”并创建新文档时,使用此处指定的条件而不是使用在语句的查询部分中设置的字段值。

当然,如果您真正想要的是数组中内容的完全匹配,那么只需将其用于查询:

query: {
    "criteria" : [{ "key1": "2015610" }, { "key2": "2096955" }]
}

然后,MongoDB很乐意在创建新文档时应用这些值,并且不会对如何解释$all表达式感到困惑。