MongoDB聚合嵌套值

时间:2019-02-26 22:04:11

标签: mongodb aggregation-framework

在MongoDB集合中,数据嵌套在absence数组中。

{
"_id" : ObjectId("5c6c62f3d0e85e6ae3a8c842"),
"absence" : [
    {
        "date" : ISODate("2017-05-10T17:00:00.000-07:00"),
        "code" : "E",
        "type" : "E",
        "isPartial" : false
    },
    {
        "date" : ISODate("2018-02-24T16:00:00.000-08:00"),
        "code" : "W",
        "type" : "E",
        "isPartial" : false
    },
    {
        "date" : ISODate("2018-02-23T16:00:00.000-08:00"),
        "code" : "E",
        "type" : "E",
        "isPartial" : false
    },
    {
        "date" : ISODate("2018-02-21T16:00:00.000-08:00"),
        "code" : "U",
        "type" : "U",
        "isPartial" : false
    },
    {
        "date" : ISODate("2018-02-20T16:00:00.000-08:00"),
        "code" : "R",
        "type" : "E",
        "isPartial" : false
    }
]
}

我想按absence.type进行汇总,以返回每种类型的计数以及absence个孩子的总数。结果可能看起来像:

{
    "_id" : ObjectId("5c6c62f3d0e85e6ae3a8c842"),
    "U" : 1,
    "E" : 4,
    "total" : 5
}

这里也发布了几个类似的问题,但我尚未成功调整我的模式的答案。任何帮助将不胜感激。

此外,是否有GUI建模工具可帮助构建MongoDB查询?从RDBMS查询到Mongo聚合管道的转换非常困难。

2 个答案:

答案 0 :(得分:2)

您可以使用以下汇总:

db.col.aggregate([
    {  
        $unwind: "$absence" 
    },
    {
        $group: {
            _id: { _id: "$_id", type: "$absence.type" },
            count: { $sum: 1 }
        }
    },
    {
        $group: {
            _id: "$_id._id",
            types: { $push: { k: "$_id.type", v: "$count" } },
            total: { $sum: "$count" }
        }
    },
    {
        $replaceRoot: {
            newRoot: {
                $mergeObjects: [ "$$ROOT", { $arrayToObject: "$types" } ]
            }
        }
    },
    {
        $project: {
            types: 0
        }
    }
])

$unwind可让您每个absence获得一个文档。然后,您需要加倍$group,第一个用type_id来计数,第二个则是每个_id的数据汇总。每个_id只有一个文档,您只需要$replaceRoot$mergeObjects即可将您动态创建的键和值(按$arrayToObject)提升到根级别。

输出:

{ "_id" : ObjectId("5c6c62f3d0e85e6ae3a8c842"), "total" : 5, "U" : 1, "E" : 4 }

答案 1 :(得分:0)

如果您知道“ absence.type”的所有可能值,则对值对该数组进行$ filter并计算已过滤数组的$ size。如果您不知道“ absence.type”中的所有可能值,则此方法将无效。

db.col.aggregate([

    { $project: { U: { $size: { $filter: { input: "$absence", as: "a", cond: { $eq: [ "$$a.type", "U"]}  }}}, 
                    E: { $size: { $filter: { input: "$absence", as: "a", cond: { $eq: [ "$$a.type", "E"]}  }}} }},
    { $project: { total: { $add: [ "$U", "$E" ]}, U: 1, E: 1}},

])