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

MongoDB执行$unwind和$match后如何分组恢复原文档结构?

问题描述

使用如下示例数据:

{
 _id: 1,
 zipcode: 63109,
 students: [
              { name: "john", school: 102, age: 10 },
              { name: "jess", school: 102, age: 11 },
              { name: "jeff", school: 108, age: 15 }
           ]
}
{
 _id: 2,
 zipcode: 63110,
 students: [
              { name: "ajax", school: 100, age: 7 },
              { name: "achilles", school: 100, age: 8 },
           ]
}

{
 _id: 3,
 zipcode: 63109,
 students: [
              { name: "ajax", school: 100, age: 7 },
              { name: "achilles", school: 100, age: 8 },
           ]
}

{
 _id: 4,
 zipcode: 63109,
 students: [
              { name: "barney", school: 102, age: 7 },
           ]
}

为了获取students数组中所有匹配school:102的元素(因为$elemMatch只能返回第一个匹配项),使用了以下聚合管道:

db.zip.aggregate(
  {$match: {zipcode: 63109}},
  {$unwind: "$students"},
  {$match: {"students.school": 102}}
)

当前得到的结果是:

[{
        "_id": 1,
        "zipcode": 63109,
        "students": {
            "name": "john",
            "school": 102,
            "age": 10
        }
    }, {
        "_id": 1,
        "zipcode": 63109,
        "students": {
            "name": "jess",
            "school": 102,
            "age": 11
        }
    }, {
        "_id": 4,
        "zipcode": 63109,
        "students": {
            "name": "barney",
            "school": 102,
            "age": 7
        }
    }
]

但需要的是与原文档一致的结构,即:

[{
        "_id": 1,
        "zipcode": 63109,
        "students": [{
                "name": "john",
                "school": 102,
                "age": 10
            }, {
                "name": "jess",
                "school": 102,
                "age": 11
            }
        ]
    }, {
        "_id": 4,
        "zipcode": 63109,
        "students": [{
                "name": "barney",
                "school": 102,
                "age": 7
            }
        ]
    }
]

请问需要在聚合管道中添加什么步骤?


解决方案

需要在现有管道末尾添加$group阶段,将拆分后的文档重新按_id分组,把匹配的students元素重新聚合为数组,同时保留zipcode字段。

完整聚合管道代码:

db.zip.aggregate([
  {$match: {zipcode: 63109}},
  {$unwind: "$students"},
  {$match: {"students.school": 102}},
  {$group: {
      _id: "$_id",
      zipcode: {$first: "$zipcode"},
      students: {$push: "$students"}
    }}
])

各阶段说明:

  • $match:筛选出zipcode为63109的文档,减少后续处理的数据量。
  • $unwind:将students数组拆分为单个文档,每个文档对应数组中的一个元素。
  • $match:筛选出students.school等于102的文档,过滤掉不符合条件的学生元素。
  • $group:
    • 按_id分组,确保每个原始文档对应一个分组结果。
    • 使用$first获取zipcode(同一分组内的zipcode值一致)。
    • 使用$push将分组内的单个students对象重新组装为数组,恢复原文档的数组结构。

执行上述管道后,就能得到符合要求的结构结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 00:30:57