如何将MongoDB中多个同集合$lookup合并为单个?
合并多个针对同一集合的$lookup聚合操作
可以通过收集所有关联ID、单次$lookup后映射字段的方式,把多次针对category集合的关联合并成一次,减少数据库IO开销,优化查询性能。
优化后的聚合查询
db.story.aggregate([ // 第一步:把所有需要关联的分类ID收集到一个数组中 { $addFields: { category_ids: ["$category_id", "$sub_category_id", "$l3_sub_category_id", "$l4_sub_category_id"] } }, // 第二步:单次$lookup获取所有匹配的分类数据 { $lookup: { from: "category", localField: "category_ids", foreignField: "_id", as: "all_categories" } }, // 第三步:将批量获取的分类数据映射到对应的字段上 { $addFields: { category_data: { $filter: { input: "$all_categories", cond: { $eq: ["$$this._id", "$category_id"] } } }, sub_category_data: { $filter: { input: "$all_categories", cond: { $eq: ["$$this._id", "$sub_category_id"] } } }, l3_sub_category_data: { $filter: { input: "$all_categories", cond: { $eq: ["$$this._id", "$l3_sub_category_id"] } } }, l4_sub_category_data: { $filter: { input: "$all_categories", cond: { $eq: ["$$this._id", "$l4_sub_category_id"] } } } } }, // 第四步:移除临时字段,保持输出格式和原查询一致 { $project: { category_ids: 0, all_categories: 0 } } ])
替代优化方案(利用分类level字段)
如果你的category集合中level字段和层级严格对应(level=1对应一级分类,level=2对应二级,以此类推),可以用level来过滤数据,代码更简洁:
db.story.aggregate([ { $addFields: { category_ids: ["$category_id", "$sub_category_id", "$l3_sub_category_id", "$l4_sub_category_id"] } }, { $lookup: { from: "category", localField: "category_ids", foreignField: "_id", as: "all_categories" } }, { $addFields: { category_data: { $filter: { input: "$all_categories", cond: { $eq: ["$$this.level", 1] } } }, sub_category_data: { $filter: { input: "$all_categories", cond: { $eq: ["$$this.level", 2] } } }, l3_sub_category_data: { $filter: { input: "$all_categories", cond: { $eq: ["$$this.level", 3] } } }, l4_sub_category_data: { $filter: { input: "$all_categories", cond: { $eq: ["$$this.level", 4] } } } } }, { $project: { category_ids: 0, all_categories: 0 } } ])
效果说明
两种方案的输出结果和你原来多次$lookup的结果完全一致,但只需要和category集合建立一次关联,在数据量较大时性能提升明显。
内容的提问来源于stack exchange,提问作者Shreyas H
相关产品推荐
相关产品推荐

