这是我的测试集:
>db.test.find()
{
"_id": ObjectId("54906479e89cdf95f5fb2351"),
"reports": [
{
"desc": "xxx",
"order": {"$id": ObjectId("53fbede62827b89e4f86c12e")}
}
]
},
{
"_id": ObjectId("54906515e89cdf95f5fb2352"),
"reports": [
{
"desc": "xxx"
}
]
},
{
"_id": ObjectId("549067d3e89cdf95f5fb2353"),
"reports": [
{
"desc": "xxx"
}
]
}
我想用订单统计所有文件和文件,所以:
>db.test.aggregate({
$group: {
_id: null,
all: {
$sum: 1
},
order: {
$sum: {
"$cond": [
{
"$ifNull": ["$reports.order", false]
},
1,
0
]
}
}
}
})
和我的结果:
{
"result" : [
{
"_id" : null,
"all" : 3,
"order" : 3
}
],
"ok" : 1
}
但预计:
{
"result" : [
{
"_id" : null,
"all" : 3,
"order" : 1
}
],
"ok" : 1
}
我将放置的内容没有区别 - “$ reports.order”,“$ reports.xxx”等,只有当字段报告存在时才会检查聚合框架,忽略嵌入。 $ ifNull和$ eq dos不能用于嵌入文档吗? 有办法做这样的事吗
db.test.find({"reports.order": {$exists: 1}})
在聚合框架中? 对不起我的英语,我希望你明白我想给你看的东西:)
答案 0 :(得分:0)
我认为它不起作用,因为该领域"报告"包含一个数组,而不是一个对象。
我的意思是,您的聚合在此集合中按预期工作:
>db.test.find()
{
"_id": ObjectId("54906479e89cdf95f5fb2351"),
"reports":
{
"desc": "xxx",
"order": {"$id": ObjectId("53fbede62827b89e4f86c12e")}
}
},
{
"_id": ObjectId("54906515e89cdf95f5fb2352"),
"reports":
{
"desc": "xxx"
}
},
{
"_id": ObjectId("549067d3e89cdf95f5fb2353"),
"reports":
{
"desc": "xxx"
}
}
请注意,我删除了" ["和"]",所以现在它是一个对象,而不是一个数组(一对一的关系)。
因为你在"报告中有数组"在字段中,您需要展开数组以为每个元素输出一个文档。我想如果你有两个"命令" "报告"内的字段数组,你只想数一次。我的意思是:
"reports": [
{
"desc": "xxx",
"order": {"$id": ObjectId("53fbede62827b89e4f86c12e")},
"order": "yyy",
}
]
只应算作最终对象的一个" order"总和。
在这种情况下,您需要展开,按_id分组(因为前面的示例为同一个_id输出两个文档),然后再次分组以计算所有文档:
db.test.aggregate([
{$unwind: '$reports'},
{$group:{
_id:"$_id",
order:{$sum:{"$cond": [
{
"$ifNull": ["$reports.order", false]
},
1,
0
]
}
}
}},
{$group:{
_id:null,
all:{$sum:1},
order: {
$sum:{
"$cond": [{$eq: ['$order', 0]}, 0, 1]
}
}
}}])
也许有一个更短的解决方案,但这可行。