本文介绍如何使用 mongodb 聚合管道(`$unwind` + `$replaceroot`)将嵌套在 `bills` 字段中的子文档数组“展平”为顶层文档数组,彻底移除冗余的外层键名,获得纯净的子文档列表。
在 MongoDB 查询中,当你通过投影(projection)仅获取嵌套字段(如 { bills: 1 })时,返回结果仍会保留原始结构:整个文档以 { bills: [...] } 形式包裹,而非直接返回数组内容。这在前端渲染或 API 响应中往往不符合预期——你真正需要的是扁平化的子文档数组,而非带键名的包装对象。
解决该问题的核心思路是脱离简单查询(find),改用聚合管道(aggregate)进行结构转换。具体需两个关键阶段:
bills 数组展开为多条独立文档(每条对应一个子文档); ✅ 正确的聚合查询示例如下(Node.js + MongoDB Driver):
const { ObjectId } = require('mongodb');
const billsList = await record.aggregate([
{ $match: { _id: new ObjectId(billId) } },
{ $unwind: '$bills' },
{ $replaceRoot: { newRoot: '$bills' } }
]).toArray();✅ 输出结果即为你所需的格式:[ { "_id": "64b6d9a71dd7cfdb0aba40c0", "title": "Month1" }, { "_id": "62b6d9a71dd7cfdb0aba40c0", "title": "Month2" } ]
? 注意事项与最佳实践:
总之,$unwind + $replaceRoot 是处理“去壳取值”类需求的标准范式。它不依赖应用层循环处理,完全在数据库侧完成结构重塑,高效、声明式且易于维护。