mongodb有以下文件:
> db.test.find({name:{$in:["abc","abc2"]}})
{ "_id" : 1, "name" : "abc", "scores" : [ ] }
{ "_id" : 2, "name" : "abc2", "scores" : [ 10, 20 ] }
我希望每个文档得到得分数组长度,我该怎么做?
尝试以下命令:
db.test.aggregate({$match:{name:"abc2"}}, {$unwind: "$scores"}, {$group: {_id:null, count:{$sum:1}}} )
结果:
{ "_id" : null, "count" : 2 }
但低于命令:
db.test.aggregate({$match:{name:"abc"}}, {$unwind: "$scores"}, {$group: {_id:null, count:{$sum:1}}} )
什么也没有。问题:
答案 0 :(得分:9)
所以这实际上是一个常见的问题。数组为“空”的聚合管道中$unwind
阶段的结果是从管道结果中“删除”到文档。
为了给这样一个“空”数组返回一个“0”的计数,你需要做类似下面的事情。
在MongoDB 2.6或更高版本中,只需使用$size
:
db.test.aggregate([
{ "$match": { "name": "abc" } },
{ "$group": {
"_id": null,
"count": { "$sum": { "$size": "$scores" } }
}}
])
在早期版本中,您需要执行此操作:
db.test.aggregate([
{ "$match": { "name": "abc" } },
{ "$project": {
"name": 1,
"scores": {
"$cond": [
{ "$eq": [ "$scores", [] ] },
{ "$const": [false] },
"$scores"
]
}
}},
{ "$unwind": "$scores" },
{ "$group": {
"_id": null,
"count": { "$sum": {
"$cond": [
"$scores",
1,
0
]
}}
}}
])
现代操作很简单,因为$size
只会“测量”数组。在后一种情况下,当数组为空时,您需要用一个false
值“替换”该数组,以避免$unwind
“销毁”这个“空”语句。
因此,使用false
替换$cond
“trinary”可以选择是将1
还是0
添加到整个语句的$sum
。< / p>
这就是你得到“空数组”的长度。
答案 1 :(得分:1)
要获得2个或更多文档中的分数长度,您只需要更改 $group
管道中的_id
值,该管道包含按键划分的不同组,因此在这种情况下,您需要按文档_id
进行分组。
您的第二个聚合不返回任何内容,因为 $match
查询管道传递了一个具有空分数组的文档。要检查数组是否为空,您的匹配查询应为
{'scores.0': {$exists: true}}
或{scores: {$not: {$size: 0}}}
总的来说,您的聚合应如下所示:
db.test.aggregate([
{ "$match": {"scores.0": { "$exists": true } } },
{ "$unwind": "$scores" },
{
"$group": {
"_id": "$_id",
"count": { "$sum": 1 }
}
}
])