MongoDB中如何通过$lookup管道为关联结果保留added_at字段
解决MongoDB $lookup关联时保留added_at字段的问题
要实现关联查询同时保留inbox数组中每个元素的added_at字段,不能直接使用localField+foreignField的简化$lookup语法,因为这种方式无法将added_at与关联后的用户信息绑定。需要改用带自定义管道的$lookup,结合$unwind和$group来实现,具体聚合管道如下:
完整聚合代码
db.Users.aggregate([ // 拆分inbox数组,每个元素转为独立文档 { $unwind: "$inbox" }, // 关联用户集合,传递当前inbox的participant和added_at到内部管道 { $lookup: { from: "Users", let: { participantId: "$inbox.participant", addedAt: "$inbox.added_at" }, pipeline: [ // 匹配关联的目标用户 { $match: { $expr: { $eq: ["$_id", "$$participantId"] } } }, // 将当前的added_at字段注入关联结果 { $addFields: { added_at: "$$addedAt" } }, // 筛选需要保留的字段 { $project: { first_name: 1, last_name: 1, _id: 1, added_at: 1 } } ], as: "participant_info" } }, // 拆分关联返回的数组(每个结果仅含一个用户) { $unwind: "$participant_info" }, // 重新分组,还原原文档结构并组装participants数组 { $group: { _id: "$_id", first_name: { $first: "$first_name" }, last_name: { $first: "$last_name" }, email: { $first: "$email" }, participants: { $push: "$participant_info" } } } ])
关键步骤说明
- $unwind: "$inbox":把原文档的
inbox数组拆分为多个独立文档,确保每个participant和对应的added_at能被单独处理。 - 带变量的$lookup:
- 通过
let定义变量,将当前文档的inbox.participant和inbox.added_at传入内部管道; - 内部管道先匹配目标用户,再用
$addFields把added_at绑定到关联结果中,最后过滤出需要的字段。
- 通过
- $unwind: "$participant_info":由于
$lookup返回的是数组格式(即使仅含一个元素),拆分后方便后续分组还原结构。 - $group:按原文档
_id聚合,将所有关联后的用户信息重新组装成participants数组,同时保留原文档的基础字段。
最终结果示例
执行后得到的文档结构如下:
{ _id: ObjectId("123456789xx"), first_name: "Sam", last_name: "Jones", email: "samjones@gmail.com", participants: [ { _id: ObjectId("1XXXXXXXXX"), first_name: "Alice", last_name: "Smith", added_at: "12:00:00 09/21/2021" }, { _id: ObjectId("2XXXXXXXXX"), first_name: "Bob", last_name: "Williams", added_at: "12:00:00 11/21/2022" } ] }
内容的提问来源于stack exchange,提问作者Shaun
相关产品推荐
相关产品推荐

