MongoDB多层$group聚合如何输出嵌套文档而非数组
问题原因
你之前的写法出现内容截断是因为$arrayToObject要求数组中每个元素的k值唯一,同一个type的多条数据会被后续同key的条目覆盖,只会保留最后一条;多余的data字段是因为你没有将嵌套的结构提升到文档根层级。
纯聚合管道实现方案(无需JS,性能友好)
整个 pipeline 均使用MongoDB原生聚合算子,计算效率远高于JS遍历,适合低配置服务器处理大数据量:
db.collection.aggregate([ // 第一步:按三层维度先做最细粒度分组,提前压缩数据量 { $group: { _id: { class: "$class", type: "$type", color: "$color" }, docs: { $push: "$$ROOT" } // 保留所有字段,不需要手动逐一指定 } }, // 第二步:按class+type分组,生成type下color到文档数组的映射 { $group: { _id: { class: "$_id.class", type: "$_id.type" }, colorMap: { $push: { k: "$_id.color", v: "$docs" } } } }, { $addFields: { colorMap: { $arrayToObject: "$colorMap" } } }, // 第三步:按最上层class分组,生成class下type到color映射的结构 { $group: { _id: "$_id.class", typeMap: { $push: { k: "$_id.type", v: "$colorMap" } } } }, { $addFields: { typeMap: { $arrayToObject: "$typeMap" } } }, // 第四步:将结构提升到根层级,去掉多余的嵌套字段 { $replaceRoot: { newRoot: { $mergeObjects: [ { _id: "$_id" }, "$typeMap" ] } } } ], { allowDiskUse: true }) // 开启磁盘暂存,避免低内存服务器出现溢出报错
性能优化建议
- 提前为
class、type、color字段建立复合索引,可大幅加快分组排序速度 - 若不需要保留原文档的所有字段,可在第一步
$push时手动指定需要的字段,减少内存占用
内容的提问来源于stack exchange,提问作者YoomarXD
相关产品推荐
相关产品推荐

