MongoDB聚合实现:提取用户关联posts下所有medias生成外层独立数组
MongoDB聚合实现用户关联posts所有媒体文件汇总
你可以在原有$lookup关联posts的聚合管道基础上,新增阶段实现外层medias字段的汇总,以下提供两种实现方案:
方案1:$reduce直接合并(推荐)
无需拆分原文档结构,性能更高,不需要手动保留原有字段:
db.user.aggregate([ // 你原有逻辑:关联posts集合 { $lookup: { from: "posts", localField: "_id", foreignField: "userId", as: "posts" } }, // 新增阶段:汇总外层medias字段 { $addFields: { // 不去重的写法 medias: { $reduce: { input: "$posts", initialValue: [], in: { $concatArrays: ["$$value", "$$this.medias"] } } } // 需要去重的话替换为下面的写法: /* medias: { $setUnion: { $reduce: { input: "$posts", initialValue: [], in: { $concatArrays: ["$$value", "$$this.medias"] } } } } */ } } ])
逻辑说明:通过$reduce遍历所有post文档,将每个post的medias数组拼接为一个大数组,需要去重时用$setUnion对拼接后的数组做去重处理即可。
方案2:$unwind拆分实现
适合需要对媒体文件做额外过滤、二次处理的场景:
db.user.aggregate([ // 原有关联逻辑 { $lookup: { from: "posts", localField: "_id", foreignField: "userId", as: "posts" } }, // 拆分posts数组 { $unwind: "$posts" }, // 拆分每个post下的medias数组,preserveNullAndEmptyArrays参数兼容没有medias的post { $unwind: { path: "$posts.medias", preserveNullAndEmptyArrays: true } }, // 分组还原用户结构 { $group: { _id: "$_id", // 保留用户原有所有字段 fullName: { $first: "$fullName" }, email: { $first: "$email" }, password: { $first: "$password" }, avatar: { $first: "$avatar" }, friends: { $first: "$friends" }, friendRequests: { $first: "$friendRequests" }, // 还原posts数组 posts: { $push: "$posts" }, // 汇总medias:$push不去重,$addToSet自动去重 medias: { $push: "$posts.medias" } // 去重替换为:medias: { $addToSet: "$posts.medias" } } } ])
内容的提问来源于stack exchange,提问作者Vishnu Mohan
相关产品推荐
相关产品推荐

