MongoDB聚合:展示包含父文档信息的所有子文档
MongoDB聚合:为子文档添加父文档字段
集合结构
[ { inv_name: "Client 1", inv_date: 2022-12-20T05:09:09.803Z, inv_ready: false, inv_payments: [ { id: "123", pay_amount: 32.45 }, { id: "456", pay_amount: 55.60 } ] }, { inv_name: "Client 2", inv_date: 2022-12-19T05:09:09.803Z, inv_ready: true, inv_payments: [ { id: "459", pay_amount: 67.45 }, { id: "556", pay_amount: 30.60 } ] } ]
目标结果
提取每个inv_payments子文档,添加父文档的inv_name作为client字段,同时将子文档的id重命名为pay_date,最终输出:
[ { "client": "Client 1", "pay_amount": 32.45, "pay_date": "123" }, { "client": "Client 1", "pay_amount": 55.6, "pay_date": "456" }, { "client": "Client 2", "pay_amount": 67.45, "pay_date": "459" }, { "client": "Client 2", "pay_amount": 30.6, "pay_date": "556" } ]
尝试的聚合代码
db.invoices.aggregate([ { "$project": { _id: 0, "inv_payments": { $reduce: { input: "$inv_payments", initialValue: [], in: { $concatArrays: [ [ { client: "$this.name", pay_id: "$$this.id", pay_amount: "$$this.pay_amount" } ], "$inv_payments" ] } } } } }, { $unwind: "$inv_payments" }, { $replaceRoot: { newRoot: "$inv_payments" } } ])
问题分析与修正方案
你的代码存在3个核心问题:
$reduce逻辑错误:每次循环都拼接原始$inv_payments数组,会导致无限重复,且未使用$reduce的累加器$$value来构建结果数组。- 字段引用错误:父文档的客户名字段是
inv_name,不是$this.name,正确引用应为$inv_name。 - 字段命名不符:目标结果需要
pay_date,但代码中写的是pay_id。
以下是两种更简洁的可行方案:
方案一:$unwind + $project(最直接)
db.invoices.aggregate([ // 展开inv_payments数组,将每个子文档转为独立文档 { $unwind: "$inv_payments" }, // 投影并重构字段,关联父文档信息 { $project: { _id: 0, client: "$inv_name", pay_amount: "$inv_payments.pay_amount", pay_date: "$inv_payments.id" } } ])
方案二:$map处理数组 + $unwind + $replaceRoot
如果希望先在数组内完成字段重构再展开:
db.invoices.aggregate([ { $project: { _id: 0, payments: { $map: { input: "$inv_payments", as: "pay", in: { client: "$inv_name", pay_amount: "$$pay.pay_amount", pay_date: "$$pay.id" } } } } }, { $unwind: "$payments" }, { $replaceRoot: { newRoot: "$payments" } } ])
两种方案都能精准输出目标结果,逻辑比$reduce更清晰,适配你的需求场景。
内容的提问来源于stack exchange,提问作者Caldera500
相关产品推荐
相关产品推荐

