如何修改MongoDB聚合查询的结果输出格式?
Flatten Nested
data Fields to Top-Level in MongoDB Aggregation Results 绝对可以搞定!你只需要在现有的聚合管道末尾添加一个阶段,把嵌套在data里的字段展开到顶层就行。这里有两种常用的方法,你可以根据自己的需求选择:
方法1:用$mergeObjects + $replaceRoot(灵活适配多字段)
这种方法适合data对象里的字段较多或者可能变化的场景,它会自动把data的所有字段合并到顶层,同时保留你需要的聚合结果字段:
db.metrics.aggregate([ { $unwind: "$data" }, { $group: { _id: "$data.configName", avg: { $avg: "$data.linesCount" }, lastData: { $last: "$data" }, // 重命名避免和后续合并字段冲突 date: { $last: "$date" } } }, { $replaceRoot: { newRoot: { $mergeObjects: [ "$lastData", // 先把data里的所有字段放进去 { avg: "$avg", date: "$date", _id: "$_id", fileFormat: "" // 强制添加空值的fileFormat(如果原data没有的话) } ] } } } ]).pretty()
原理说明:
- 在
$group阶段把原data字段重命名为lastData,避免后续合并时的字段冲突 - 用
$mergeObjects把lastData的所有字段和顶层的avg、date、_id(还有你需要的fileFormat默认值)合并成一个新对象 - 最后用
$replaceRoot把这个合并后的对象作为最终返回的根文档,自动实现字段展开
方法2:用$project显式指定字段(精准可控)
如果data里的字段是固定的,你也可以直接在$group阶段就把需要的字段单独提取出来,省去后续的合并步骤:
db.metrics.aggregate([ { $unwind: "$data" }, { $group: { _id: "$data.configName", avg: { $avg: "$data.linesCount" }, configName: { $last: "$data.configName" }, linesCount: { $last: "$data.linesCount" }, insertedLinesCount: { $last: "$data.insertedLinesCount" }, fileFormat: { $last: "$data.fileFormat", $literal: "" }, // 给默认空值 date: { $last: "$date" } } } ]).pretty()
原理说明:
直接在$group阶段通过$last提取data里的每个字段,同时设置fileFormat的默认值(用$literal确保即使原数据没有这个字段也会返回空字符串),这样聚合完成后直接就是你想要的顶层字段格式。
两种方法都能得到你期望的输出结果:
{ "_id" : "aaa", "avg" : 500, "configName" : "aaa", "linesCount" : 500, "insertedLinesCount" : 658, "fileFormat" : "", "date" : "20150220" }
内容的提问来源于stack exchange,提问作者Adam Hasan
相关产品推荐
相关产品推荐

