mongodb $聚合空数组和多个文件

Jam*_*ang 5 mongodb mongodb-query aggregation-framework

mongodb有以下文件:

> db.test.find({name:{$in:["abc","abc2"]}})
{ "_id" : 1, "name" : "abc", "scores" : [ ] }
{ "_id" : 2, "name" : "abc2", "scores" : [ 10, 20 ] }
Run Code Online (Sandbox Code Playgroud)

我希望得到每个文档的分数长度,我该怎么办?

尝试下面的命令:

db.test.aggregate({$match:{name:"abc2"}}, {$unwind: "$scores"}, {$group: {_id:null, count:{$sum:1}}} )
Run Code Online (Sandbox Code Playgroud)

结果:

{ "_id" : null, "count" : 2 }
Run Code Online (Sandbox Code Playgroud)

但是在命令之下:

db.test.aggregate({$match:{name:"abc"}}, {$unwind: "$scores"}, {$group: {_id:null, count:{$sum:1}}} )
Run Code Online (Sandbox Code Playgroud)

什么也没有.题:

  1. 如何在一个命令中获得2个或更多文档中的每个分数?
  2. 为什么第二个命令的结果什么都没有?我应该如何检查数组是否为空?

Nei*_*unn 10

所以这实际上是一个常见的问题.$unwind数组为"空"的聚合管道中的阶段结果是从管道结果中"删除"到文档.

为了给这样一个"空"数组返回一个"0"的计数,你需要做类似下面的事情.

在MongoDB 2.6或更高版本中,只需使用$size:

db.test.aggregate([
    { "$match": { "name": "abc" } },
    { "$group": {
       "_id": null,
       "count": { "$sum": { "$size": "$scores" } }
    }}
])
Run Code Online (Sandbox Code Playgroud)

在早期版本中,您需要这样做:

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
            ]
        }}
    }}
])
Run Code Online (Sandbox Code Playgroud)

现代操作很简单,因为它$size只是"测量"阵列.在后一种情况下,当数组false为空时,你需要用一个值"替换" 它,以避免$unwind"破坏"这个"空"语句.

因此,与取代false允许$cond"三元"来选择是否添加10$sum整体的语句.

这就是你得到"空数组"的长度.


chr*_*dam 6

要获取 2 个或更多文档中的分数长度,您只需更改包含不同键组的管道_id中的值,因此在这种情况下,您需要按文档进行分组。$group_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 }
        }
    }
])
Run Code Online (Sandbox Code Playgroud)