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
相关产品推荐
相关产品推荐

