【问题标题】:MongoDB aggregate map by key and sum valueMongoDB 按键和值聚合映射
【发布时间】:2021-09-14 17:59:20
【问题描述】:

我想按键聚合以下内容并对值求和:

{
    "_id": {
        "$oid": "60dd5e0bd0ba24343dabc626"
    },
    "s": {
        "_71vnohpi4": {
            "q": 2
        }
    }
},
{
    "_id": {
        "$oid": "609ea0b0c85ca8e54adc610c"
    },
    "s": {
        "_71vnohpi4": {
            "q": 49
        },
        "_h2121audz": {
            "q": 20
       }
    }
}

想要总结如下的值:

{
    "_id": {
        "$oid": "newid-doesntmatter"
    },
    "s": {
        "_71vnohpi4": {
            "q": 51
        },
        "_h2121audz": {
            "q": 20
       }
    }
}

大多数可用的示例都适用于数组,因此$unwind 在我的情况下不起作用。而且由于键是动态的,我无法指定键名。

这是我尝试过的,但我无法对键进行分组。

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

    $objectToArray$arrayToObject等聚合运算符:

    1. 对象转数组(键值对)

    2. 展开以拆分成单独的文档。

    3. 再次将值 Object 转换为数组,因为它又是一个对象。

    4. 再次放松

    5. 基于idkey 的组(这将给出总和)

    6. 组合最里面的键/值的小组阶段。

    7. 组合所有文档的小组阶段。

    8. 使用$arrayToObject 进行项目以到达单个对象。

      [{
      '$project': {
              's': {
                  '$objectToArray': '$s'
              }
          }
      }, {
          '$unwind': '$s'
      }, {
         '$addFields': {
              's-v': {
                  '$objectToArray': '$s.v'
              }
          }
      }, {
          '$unwind': '$s-v'
      }, {
          '$group': {
              '_id': {
                  'id': '$s.k',
                  'key': '$s-v.k'
              },
              'stats': {
                  '$sum': '$s-v.v'
              }
          }
      }, {
          '$group': {
              '_id': '$_id.id',
              'sum': {
                  '$mergeObjects': {
                      '$arrayToObject': [
                          [
                              [
                                  '$_id.key', '$stats'
                              ]
                          ]
                      ]
                  }
              }
          }
      }, {
          '$group': {
              '_id': '1',
              'obj': {
                  '$push': {
                      'k': '$_id',
                      'v': '$sum'
                   }
               }
           }
      }, {
          '$project': {
              'final': {
                  '$arrayToObject': '$obj'
              }
          }
      }]
      

    【讨论】:

    【解决方案2】:
    • $objectToArrays 对象转换为键值格式的对象数组
    • $unwind 解构 s 数组
    • $group 按键并计算q 的值
    • $group通过null构造键值对对象数组
    • $arrayToObject 将上面的s 数组从键值对转换为对象
    db.collection.aggregate([
      { $project: { s: { $objectToArray: "$s" } } },
      { $unwind: "$s" },
      {
        $group: {
          _id: "$s.k",
          count: { $sum: "$s.v.q" }
        }
      },
      {
        $group: {
          _id: null,
          s: {
            $push: { k: "$_id", v: { q: "$count" } }
          }
        }
      },
      { $project: { s: { $arrayToObject: "$s" } } }
    ])
    

    Playground

    【讨论】:

    • 如果内部必须对象的键不是'q',这将不起作用。
    • OP 在问题中没有提到这一点。他要求提供动态的“_71vnohpi4”键。
    猜你喜欢
    • 2016-07-03
    • 1970-01-01
    • 2015-10-31
    • 1970-01-01
    • 2021-03-27
    • 2020-09-05
    • 1970-01-01
    • 1970-01-01
    • 2019-04-29
    相关资源
    最近更新 更多