【问题标题】:MongoDB aggregate nested groupingMongoDB聚合嵌套分组
【发布时间】:2018-12-09 05:29:14
【问题描述】:

我有资产集合,其中包含类似的数据

{
     "_id" : ObjectId("5bfb962ee2a301554915"),
     "users" : [
                 "abc.abc@abc.com",
                 "abc.xyz@xyz.com"
          ],
     "remote" : {
                "source" : "dropbox",
                "bytes" : 1234
}
{
     "_id" : ObjectId("5bfb962ee2a301554915"),
     "users" : [
                 "pqr.pqr@pqr.com",
          ],
     "remote" : {
                "source" : "google_drive",
                "bytes" : 785
}
{
     "_id" : ObjectId("5bfb962ee2a301554915"),
     "users" : [
                 "abc.abc@abc.com",
                 "abc.xyz@xyz.com"
          ],
     "remote" : {
                "source" : "gmail",
                "bytes" : 5647
}

我正在寻找的是按用户分组并根据其来源获取总字节数

{
    "_id" : "abc.abc@abc.com",
    "bytes" : {
                 "google_drive": 1458,
                 "dropbox" : 1254
              }
}

我不知道如何使用分组获取嵌套输出。 我试过查询

db.asset.aggregate(
     [
        {$unwind : '$users'},
        {$group:{
                 _id:
                    {'username': "$users", 
                    'source': "$remote.source", 
                    'total': {$sum: "$remote.bytes"}} }
        }
    ]
)

这样我就得到了重复用户名的结果。

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    在 MongoDb 3.6 和更新版本中,您可以在 $mergeObjects 表达式和 $replaceRoot 中利用 $arrayToObject 运算符> 管道以获得所需的结果。

    您需要运行以下聚合管道:

    db.asset.aggregate([
        { "$unwind": "$users" },
        { "$group": {
            "_id": { 
                "users": "$users",
                "source": "$remote.source" 
            },
            "totalBytes": { "$sum": "$remote.bytes" }
        } },
        { "$group": {
            "_id": "$_id.users",
            "counts": {
                "$push": {
                    "k": "$_id.source",
                    "v": "$totalBytes"
                }
            }
        } },
        { "$replaceRoot": { 
            "newRoot": { 
                "$mergeObjects": [ 
                    { "bytes": { "$arrayToObject": "$counts" } }, 
                    "$$ROOT" 
                ] 
            } 
        } },
        { "$project": { "counts": 0 } }   
    ])
    

    产生

    /* 1 */
    {
        "bytes" : {
            "gmail" : 5647.0,
            "dropbox" : 1234.0
        },
        "_id" : "abc.abc@abc.com"
    }
    
    /* 2 */
    {
        "bytes" : {
            "google_drive" : 785.0
        },
        "_id" : "pqr.pqr@pqr.com"
    }
    
    /* 3 */
    {
        "bytes" : {
            "gmail" : 5647.0,
            "dropbox" : 1234.0
        },
        "_id" : "abc.xyz@xyz.com"
    }
    

    使用上述示例文档。

    【讨论】:

      【解决方案2】:

      您必须在这里使用$group 几次。首先使用userssource,然后使用$sum 计算总字节数。

      其次将users$push sourcebytes 放入一个数组中

      db.collection.aggregate([
        { "$unwind": "$users" },
        { "$group": {
          "_id": {
            "users": "$users",
            "source": "$remote.source"
          },
          "bytes": { "$sum": "$remote.bytes" }
        }},
        { "$group": {
          "_id": "$_id.users",
          "data": {
            "$push": {
              "source": "$_id.source",
              "bytes": "$bytes"
            }
          }
        }}
      ])
      

      即使您想将sourcebytes 转换为键值格式,也请将最后一个$group 阶段替换为以下两个阶段。

      { "$group": {
        "_id": "$_id.users",
        "data": {
          "$push": {
            "k": "$_id.source",
            "v": "$bytes"
          }
        }
      }},
      { "$project": {
        "_id": 0,
        "username": "$_id",
        "bytes": { "$arrayToObject": "$data" }
      }}
      

      【讨论】:

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