我有一个集合:
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
答案 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
表达式感到困惑。