MongoDB如何实现嵌套数组内文档跨集合关联并保留原有字段
解决方案
你之前$group丢失contentId字段的核心原因是:$group 阶段只会输出你显式声明的字段,未在聚合配置中定义的字段不会默认保留,由于同一个sceneId对应的contentId是固定值,使用$first/$last运算符提取即可。
以下是两种可直接运行的实现方案:
方案1:兼容全版本,写法直观
db.Scenes.aggregate([ // 展开评论数组,单条评论对应一条临时文档 { $unwind: "$comments" }, // 关联用户集合拉取头像信息 { $lookup: { from: "Userdatas", localField: "comments.userId", foreignField: "userId", as: "userInfo" } }, // 提取关联返回的用户数据 { $unwind: "$userInfo" }, // 把头像字段合并到评论对象中 { $addFields: { "comments.profilPicture": "$userInfo.profilPicture" } }, // 重新按原文档分组,恢复评论数组结构 { $group: { _id: "$_id", sceneId: { $first: "$sceneId" }, contentId: { $first: "$contentId" }, // 显式声明保留contentId,解决字段丢失问题 comments: { $push: "$comments" } } }, // 调整输出格式,隐藏内部_id字段 { $project: { _id: 0, sceneId: 1, contentId: 1, comments: 1 } } ])
方案2:MongoDB 3.6+ 高性能写法,无需拆分数组
db.Scenes.aggregate([ // 一次性拉取当前文档所有评论对应的用户信息 { $lookup: { from: "Userdatas", localField: "comments.userId", foreignField: "userId", as: "userMaps" } }, // 遍历评论数组,匹配对应用户的头像字段 { $addFields: { comments: { $map: { input: "$comments", as: "comment", in: { $mergeObjects: [ "$$comment", { profilPicture: { $getField: { input: { $first: { $filter: { input: "$userMaps", cond: { $eq: ["$$this.userId", "$$comment.userId"] } } } }, field: "profilPicture" } } } ] } } } } }, // 删除临时的用户映射字段 { $project: { userMaps: 0 } } ])
两种方案的输出结果完全符合你要求的格式,可根据你的MongoDB版本和数据量级选择使用。
内容的提问来源于stack exchange,提问作者Noltibus
相关产品推荐
相关产品推荐

