我在名为Objects
的mongo集合中获得了以下两个cars
:
{vendor: "BMW",
model: "325i",
class: "coupe",
equipment: [
{name: "airbag",
cost: 120
},
{name: "led",
cost: 170
},
{name: "abs",
cost: 150
}
]
}
{vendor: "Mercedes",
model: "C 250",
class: "coupe",
equipment: [
{name: "airbag",
cost: 180
},
{name: "esp",
cost: 170
},
{name: "led",
cost: 120
}
]
}
我正在使用Mongo 2.6中引入的新聚合功能redact
我想执行查询以获取带有过滤设备部件的汽车列表。
用语言:给我所有类型的轿跑车,只提供有关LED
和AIRBAG
设备的信息。
我已尝试过这种聚合:
db.cars.aggregate(
[
{$match: {"class": "coupe"}},
{$redact:
{
$cond:
{
if: { $in : ["$name", ["airbag", "led"]]},
then: "$$DESCEND",
else: "$$PRUNE"
}
}
}
]
)
但这会导致以下错误:
断言:命令失败:{" errmsg" :"异常:无效的运算符 ' $ in'","代码" :15999," ok" :0}:聚合失败
我做错了什么?是否有另一种方法来实现目标。
我希望从Mongo获得这个结果:
{vendor: "BMW",
model: "325i",
class: "coupe",
equipment: [
{name: "airbag",
cost: 120
},
{name: "led",
cost: 170
}
]
}
{vendor: "Mercedes",
model: "C 250",
class: "coupe",
equipment: [
{name: "airbag",
cost: 180
},
{name: "led",
cost: 120
}
]
}
有关如何实现这一目标的任何建议吗?
干杯, 拉尔夫
答案 0 :(得分:4)
对于这种情况,$redact
管道运算符实际上不是您想要的那个。它想要做的是递归"下降"通过文件结构并评估每个级别的条件"看看它将采取什么行动。
在你的情况下,没有"名称"文档顶层的字段,以满足条件,因此整个文档被修剪"。
您正在过滤数组,对于您不想使用$unwind
和$match
的情况,您可以使用新的运算符,例如$map
:
db.cars.aggregate([
{ "$match": { "class": "coupe" }},
{ "$project": {
"equipment": {
"$setDifference": [
{ "$map": {
"input": "$equipment",
"as": "el",
"in": {
"$cond": [
{ "$or": [
{ "$eq": [ "$$el.name", "airbag" ] },
{ "$eq": [ "$$el.name", "led" ] }
]},
{ "$cond": [ 1, "$$el", 0 ] },
false
]
}
}},
[false]
]
}
}}
])
$map
运算符使用数组并针对所有元素计算逻辑条件,在本例中为$cond
。与 $in
相同的是,在这个意义上它不是逻辑运算符,而是使用$or
,它是聚合框架的逻辑运算符。
由于任何不符合条件的项目都会返回false
,您现在需要做的是"删除"所有false
值。这得到$setDifference
的帮助,通过比较可以做到这一点。
结果就是你想要的:
{
"_id" : ObjectId("53b2725120edfc7d0df2f0b1"),
"equipment" : [
{
"name" : "airbag",
"cost" : 120
},
{
"name" : "led",
"cost" : 170
}
]
}
{
"_id" : ObjectId("53b2725120edfc7d0df2f0b2"),
"equipment" : [
{
"name" : "airbag",
"cost" : 180
},
{
"name" : "led",
"cost" : 120
}
]
}
如果您真的打算使用 $redact
,那么总有这个人为的例子:
db.cars.aggregate([
{ "$match": { "class": "coupe" }},
{ "$redact": {
"$cond": {
"if": {
"$or": [
{ "$eq": [
{ "$ifNull": ["$name", "airbag"] },
"airbag"
]},
{ "$eq": [
{ "$ifNull": ["$name", "led"] },
"led"
]},
]
},
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}}
])
所以这基本上确保如果该字段在下降时根本不存在那么它将"人为地"产生一个匹配的,以便该等级不会被修剪"。如果该字段存在,则使用找到的值,如果该值与条件不匹配,则将对其进行修剪。