问题
假设我有一份文件如下:
doc = {
"_id" : ObjectId("56464c726879571b1dcbac79"),
"food" : {
"fruit" : [
"apple",
"orange"
]
},
"items" : [
{
"item_id" : 750,
"locations" : [
{
"store#" : 13,
"num_employees" : 138
},
{
"store#" : 49,
"num_employees" : 343
}
]
},
{
"item_id" : 650,
"locations" : [
{
"store#" : 12,
"num_employees" : 22
},
{
"store#" : 15,
"num_employees" : 52
}
]
}
]
}
我想删除该元素
{'#store#' : 12, 'num_employees' : 22}
但只有满足以下条件:
> food.fruit包含苹果或橙子的值
> item_id的id为650
我尝试过的解决方案
我尝试了以下方法:
db.test.update({"food.fruit" : {"$in" : ["apple", "orange"]}, "items.item_id":650},{$pull:{'items.$.locations':{'store#':12,'num_employees':22}}})
更新不起作用.有趣的是,如果查询的$in运算符部分被删除,它就可以工作.我正在使用MongoDB v3.0.6并查阅MongoDB手册以使用$(更新):
https://docs.mongodb.org/manual/reference/operator/update/positional/
文档包含一段感兴趣的内容:
Nested Arrays
The positional $operator cannot be used for queries which traverse more than one array, such as queries that traverse arrays nested within other arrays, because the replacement for the $placeholder is a single value
当然,我的查询遍历多个数组.事实上,如果我从查询中删除’food.fruit’:{$in:[‘apple’]},它就可以了.但是,这样做
不解决我的问题,因为我当然需要那个查询.我正在寻找一个最好的解决方案:
>不需要架构更改
>在一个查询/更新语句中执行
最佳答案 如果您需要在“food.fruit”中匹配多个可能的值,因此需要匹配其他多个可能的文档(唯一有意义的情况),那么您始终可以在
$where
中使用JavScript逻辑替换$in:
db.test.update(
{
"items.item_id": 650,
"$where": function() {
return this.food.fruit.some(function(el) {
return ["apple","orange"].indexOf(el) != -1;
});
}
},
{ "$pull": { "items.$.locations": { "store#": 12 } } },
{ "multi": true }
)
这基本上应用相同的测试,虽然不如“food.fruit”值那样有效,但不能在索引中测试,但希望“items.item_id”的其他字段是足够的匹配,至少不会使这成为一个真正的问题.
另一方面,针对MongoDB服务器版本3.1.9(开发系列)进行测试,以下工作没有问题:
db.test.update(
{ "food.fruit": { "$in": ["orange","apple"] }, "items.item_id": 650 },
{ "$pull": { "items.$.locations": { "store#": 12 } } },
{ "multi": true }
)
我还建议,如果你打算在你的查询中包含_id,那么你只是匹配一个文档,因此你只需要提供你想要的阵列匹配到$pull
:
db.test.update(
{ "_id": 123, "items.item_id": 650 },
{ "$pull": { "items.$.locations": { "store#": 12 } } }
)
这是相当简单并且没有冲突,除非您确实需要确保实际存在所需的“food.fruits”值才能应用更新.在这种情况下,请按照前面的例子.