我有一个集合:
gStats : {
"_id" : "id1",
"criteria" : ["key1":"value1", "key2":"value2"],
"groups" : [
{"id":"XXXX", "visited":100, "liked":200},
{"id":"YYYY", "visited":30, "liked":400}
]
}
我希望能够更新给定条件数组的统计信息数组的文档(完全匹配(。
我尝试通过 2 个步骤执行此操作:
从给定"id"的数组中提取统计文档:
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
})
拉取查询工作完美。推送查询给出错误:
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
这两个查询在现实中都不起作用。您不能多次使用像"criteria"这样的键名,除非在某$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
表达式感到困惑。