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

如何在MongoDB中对嵌套数组使用分组聚合操作?

MongoDB按嵌套数组字段分组并保留原始对象的解决方案

我正尝试使用MongoDB的$group聚合操作,现有一个包含名为children的嵌套数组字段的文档,希望按children的job字段进行分组。尝试用$unwind时,返回的不是单个children对象列表,而是带有不同job的父对象副本。

测试数据

[
  {
    "name": "Peter",
    "age": 50,
    "job": "retired",
    "children": [
      {
        "name": "Alex",
        "age": 33,
        "job": "teacher",
        "children": null
      },
      {
        "name": "Jenny",
        "age": 31,
        "job": "teacher",
        "children": null
      },
      {
        "name": "Rob",
        "age": 28,
        "job": "scientist",
        "children": null
      },
      {
        "name": "Harry",
        "age": 27,
        "job": "teacher",
        "children": null
      },
      {
        "name": "Tim",
        "age": 21,
        "job": "student",
        "children": null
      }
    ]
  }
]

当前查询语句

db.collection.aggregate([
  {
    $match: {
      name: "Peter"
    }
  },
  {
    $group: {
      _id: "$children.job",
      count: {
        $sum: 1
      }
    }
  }
])

当前返回结果

[
  {
    "_id": [
      "teacher",
      "teacher",
      "scientist",
      "teacher",
      "student"
    ],
    "count": 1
  }
]

期望结果

{
  "count": {
    "teacher": 3,
    "scientist": 1,
    "student": 1
  }
}

我想知道能否获取数组的原始对象?因为$unwind返回的只是指定字段不同的父对象副本。


解决方案

1. 生成期望的count键值对结构

要得到你想要的统计结果,需要先拆解嵌套数组,再分组统计,最后转换为键值对格式:

db.collection.aggregate([
  { $match: { name: "Peter" } },
  { $unwind: "$children" },
  {
    $group: {
      _id: "$children.job",
      count: { $sum: 1 }
    }
  },
  { $project: { k: "$_id", v: "$count", _id: 0 } },
  { $group: { _id: null, count: { $push: { k: "$k", v: "$v" } } } },
  { $project: { count: { $arrayToObject: "$count" }, _id: 0 } }
])

2. 保留原始children对象的分组方式

如果需要保留每个job对应的原始子对象列表,可以在分组时用$push收集子对象:

db.collection.aggregate([
  { $match: { name: "Peter" } },
  { $unwind: "$children" },
  {
    $group: {
      _id: "$children.job",
      count: { $sum: 1 },
      children: { $push: "$children" }
    }
  },
  // 可选:转为键值对结构
  { $project: { k: "$_id", v: { count: "$count", children: "$children" }, _id: 0 } },
  { $group: { _id: null, result: { $push: { k: "$k", v: "$v" } } } },
  { $project: { result: { $arrayToObject: "$result" }, _id: 0 } }
])

返回结果示例:

{
  "result": {
    "teacher": {
      "count": 3,
      "children": [
        { "name": "Alex", "age": 33, "job": "teacher", "children": null },
        { "name": "Jenny", "age": 31, "job": "teacher", "children": null },
        { "name": "Harry", "age": 27, "job": "teacher", "children": null }
      ]
    },
    "scientist": {
      "count": 1,
      "children": [ { "name": "Rob", "age": 28, "job": "scientist", "children": null } ]
    },
    "student": {
      "count": 1,
      "children": [ { "name": "Tim", "age": 21, "job": "student", "children": null } ]
    }
  }
}

关于$unwind的优化

$unwind确实会生成父文档副本,但可以通过$project只保留需要的字段来减少冗余:

// 在$unwind后添加
{ $project: { children: 1, _id: 0 } }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 16:10:37