【问题标题】:MongoDB aggregate nested valuesMongoDB 聚合嵌套值
【发布时间】:2019-07-20 13:12:52
【问题描述】:

在 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 聚合管道的过渡非常困难。

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

    您可以使用以下聚合:

    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 }
    

    【讨论】:

    • 几乎做到了,@mickl。谢谢你。根级别对象包含我想在我的投影中返回的其他字段。我需要做什么才能投射出这些额外的字段?想象一下,数据中有一个firstnamefield,与缺勤数组处于同一级别。谢谢!
    • 您可以在$group 两个阶段中添加firstname: { $first: 'firstname' }
    【解决方案2】:

    如果您知道 "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}},
    
    ])
    

    【讨论】:

      猜你喜欢
      • 2021-03-13
      • 1970-01-01
      • 2017-07-26
      • 2017-07-16
      • 1970-01-01
      • 1970-01-01
      • 2021-03-19
      • 2021-12-02
      • 2018-07-06
      相关资源
      最近更新 更多