You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB聚合查询:按多字段分组生成指定格式统计结果

MongoDB聚合查询:合并多状态统计结果

样本集合数据

{
  "name": "test",
  "data": {
    "statusOne": "enabled",
    "statusTwo": "active"
  }
}
{
  "name": "test",
  "data": {
    "statusOne": "disabled",
    "statusTwo": "active"
  }
}
{
  "name": "another-test",
  "data": {
    "statusOne": "disabled",
    "statusTwo": "active"
  }
}

期望输出格式

需按name分组,同时统计statusOne和statusTwo各值的出现次数,最终合并到data字段中:

[
{
    "name": "test",
    "data": [
        {
            "status": "active",
            "count": 2
        },
        {
            "status": "disabled",
            "count": 1
        },
        {
            "status": "enabled",
            "count": 1
        }
    ]
},
{
    "name": "another-test",
    "data": [
        {
            "status": "active",
            "count": 1
        },
        {
            "status": "disabled",
            "count": 1
        }
    ]
}
]

我的尝试代码(未达到预期)

[
  {
    $group: {
      _id: {
        appName: "$name",
        cs: "$data.statusOne",
        ps: "$data.statusTwo",
      },
      total: {
        $sum: 1,
      },
    },
  },
  {
    $group: {
      _id: "$_id.appName",
      total: { $sum: "$total" },
      ps: {
        $addToSet: {
          name: "$_id.ps",
          count: "$total",
        },
      },
      cs: {
        $addToSet: {
          name: "$_id.cs",
          count: "$total",
        },
      },
    },
  },
  {
    $project: {
      _id: 0,
      appName: "$_id",
      items: {
        $concatArrays: ["$ps", "$cs"],
      },
    },
  },
]

正确聚合查询方案

核心思路是先把每个文档中的两个status字段拆分为独立条目,再统一统计:

[
  // 1. 将每个文档的statusOne和statusTwo转为数组形式,方便后续拆分
  {
    $addFields: {
      statusList: [
        "$data.statusOne",
        "$data.statusTwo"
      ]
    }
  },
  // 2. 拆分数组,每个status值成为单独文档
  {
    $unwind: "$statusList"
  },
  // 3. 按name和status值分组,统计每个组合的出现次数
  {
    $group: {
      _id: {
        name: "$name",
        status: "$statusList"
      },
      count: { $sum: 1 }
    }
  },
  // 4. 按name重新分组,将统计结果整理到data数组中
  {
    $group: {
      _id: "$_id.name",
      data: {
        $push: {
          status: "$_id.status",
          count: "$count"
        }
      }
    }
  },
  // 5. 调整输出字段,去掉_id,将_id转为name
  {
    $project: {
      _id: 0,
      name: "$_id",
      data: 1
    }
  }
]

步骤说明

  1. $addFields:给每个文档添加statusList数组,包含statusOne和statusTwo的取值,把两个状态字段统一成数组结构。
  2. $unwind:将数组拆分成多个文档,每个文档对应一个状态值,实现对所有状态值的统一统计。
  3. $group(第一次):按name和status值分组,计算每个状态在对应name下的出现次数。
  4. $group(第二次):按name分组,用$push将同一name下的所有统计结果整理到data数组。
  5. $project:调整输出字段名,移除系统生成的_id,将分组用的_id转为name字段,匹配期望输出格式。

内容的提问来源于stack exchange,提问作者user3518008

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 22:15:18