如何使用MongoDB嵌套lookup聚合关联workouts与exercises集合匹配练习名称
MongoDB 跨集合嵌套字段关联实现方案
方案1:兼容所有MongoDB 3.2+版本
思路是先展开嵌套数组,关联后再重组恢复原有结构,兼容性最强:
db.workouts.aggregate([ // 展开内层workouts嵌套数组,将每个元素转为单独文档 { $unwind: "$workouts" }, // 关联exercises集合,匹配workouts数组元素的_id和exercise的_id { $lookup: { from: "exercises", localField: "workouts._id", foreignField: "_id", as: "matched_exercise" } }, // 展开关联结果数组(_id唯一,只会有1条匹配结果) { $unwind: "$matched_exercise" }, // 给workout元素补充练习名称,也可直接替换原有_id字段 { $addFields: { // 新增exercise_name字段保留名称 "workouts.exercise_name": "$matched_exercise.name", // 如需直接替换_id为名称,可打开下面一行注释 // "workouts._id": "$matched_exercise.name" } }, // 按原文档_id分组,恢复原有结构和所有字段 { $group: { _id: "$_id", id_user: { $first: "$id_user" }, date: { $first: "$date" }, name: { $first: "$name" }, __v: { $first: "$__v" }, workouts: { $push: "$workouts" } } } ])
方案2:高性能优化版(MongoDB 5.0+支持)
无需拆分和重组数组,直接通过数组操作处理,性能更高,适合数据量较大的场景:
db.workouts.aggregate([ // 一次性关联所有匹配的exercise记录 { $lookup: { from: "exercises", localField: "workouts._id", foreignField: "_id", as: "exercises_list" } }, // 遍历workouts数组,给每个元素匹配补充练习名称 { $addFields: { workouts: { $map: { input: "$workouts", as: "workout_item", in: { $mergeObjects: [ "$$workout_item", { exercise_name: { $getField: { field: "name", input: { $first: { $filter: { input: "$exercises_list", cond: { $eq: ["$$this._id", "$$workout_item._id"] } } } } } } } ] } } } } }, // 移除临时关联的练习列表字段 { $project: { exercises_list: 0 } } ])
内容的提问来源于stack exchange,提问作者Albert Dąbal
相关产品推荐
相关产品推荐

