mongodb mongo聚合中$bucket边界下的动态计数字段

rsl1atfo  于 2023-01-08  发布在  Go
关注(0)|答案(1)|浏览(191)

我正在使用Mongo聚合框架,假设我有这样的集合结构

[
  {
    _id: 123,
    name: "john",
    age: 30,
    fruit: "apple",
    
  },
  {
    _id: 345,
    name: "moore",
    age: 45,
    fruit: "mango",
    
  },
  {
    _id: 545,
    name: "carl",
    age: 30,
    fruit: "grape",
    
  },
  {
    _id: 96,
    name: "shelby",
    age: 25,
    fruit: "apple",
    
  },
  {
    _id: 86,
    name: "loris",
    age: 48,
    fruit: "mango",
    
  },
  {
    _id: 76,
    name: "carl",
    age: 55,
    fruit: "grape"
  }
]

我想查询并创建一个管道,这样它就可以返回在$bucket boundaries创建的持续时间内的特定水果的计数:例如,结果应如下所示...

[
  {
    "_id": Specific_Boudary,
    "userCount": Number_Of_Users_Lie,
    "fruitsLie": [
                    {fruit_names_of_user_in_this_boundaries : fruit_counts},
                  ]
  },
  {
    "_id": 0,
    "userCount": 3,
    "fruitsLie": [
                    {apple: 2},
                    {grape: 1}
                  ]
  },
  {
    "_id": 40,
    "userCount": 2,
    "fruitsLie": [
                    {mango: 2}
                 ]
  },
  {
    "_id": "more than 50",
    "userCount": 1,
    "fruitsLie": [
                    {grape: 1}
                 ]
  }
]

因此,在30岁以下,我们有3个用户,其中2个吃苹果,1个吃葡萄,因此fruitsLie字段负责该计算。
有多少方法,我们可以实现这个问题的解决方案与具体的$桶边界,并请解释透彻的每一个阶段,我是新的聚合和目前正在学习...

mdfafbf1

mdfafbf11#

这是一种方法:

db.collection.aggregate([
  {
    "$bucket": {
      "groupBy": "$age",
      "boundaries": [
        0,
        31,
        41,
        51,
        
      ],
      "default": "More than 50",
      "output": {
        "users": {
          $push: "$$ROOT"
        }
      }
    }
  },
  {
    "$unwind": "$users"
  },
  {
    "$group": {
      "_id": {
        _id: "$_id",
        fruit: "$users.fruit"
      },
      "count": {
        "$sum": 1
      },
      
    }
  },
  {
    "$group": {
      "_id": "$_id._id",
      "fruitsLie": {
        "$push": {
          "$concatArrays": [
            [],
            [
              [
                "$$ROOT._id.fruit",
                "$$ROOT.count"
              ]
            ]
          ]
        }
      },
      usersCount: {
        $sum: "$$ROOT.count"
      }
    }
  },
  {
    "$addFields": {
      "fruitsLie": {
        "$map": {
          "input": "$fruitsLie",
          "as": "item",
          "in": {
            "$arrayToObject": "$$item"
          }
        }
      }
    }
  }
])

Playground link.
在此查询中,我们执行以下操作:
1.使用$bucket,我们按年龄将文档分组到4个bucket中:(0 - 30)、(31 - 40)、(41 - 50)和(〉50),我们将一个bucket中的所有用户收集到一个数组中。
1.现在,我们使用$unwind展开users数组。
1.现在,使用$group,我们计算每个桶中每个水果的数量。
1.再次使用$group,现在我们将每个桶的计数累加到fruitsLie数组中。
1.最后,使用$arrayToObjectfruitLie数组的元素转换为对象。

相关问题