如何使用MongoDB aggregate实现课程与学生进度集合的关联合并查询
MongoDB单聚合查询实现课程与进度合并方案
你之前的写法问题在于用unionWith只是把两个集合的结果简单堆叠,没有做字段关联合并,要实现需求应该以全量课程表为主表做左关联查询,一次聚合就能拿到符合要求的结果:
const studentName = "Tom R."; // 可替换为当前登录学生的动态变量 const result = await db .collection('classlist') // 以全量课程集合为主表,保证返回全部5门课程 .aggregate([ // 左关联当前学生的课程进度数据 { $lookup: { from: "course_progress", let: { classShortname: "$class_shortname" }, pipeline: [ { $match: { $expr: { $eq: ["$class_shortname", "$$classShortname"] }, student_name: studentName } } ], as: "progress_info" } }, // 拆开关联返回的数组,未修读的课程保留空值不被过滤 { $unwind: { path: "$progress_info", preserveNullAndEmptyArrays: true } }, // 合并课程基础字段与进度字段,无进度则仅保留课程基础信息 { $replaceRoot: { newRoot: { $mergeObjects: ["$$ROOT", "$progress_info"] } } }, // 移除冗余的中间字段 { $unset: "progress_info" } ]) .toArray();
逻辑说明
- 以
classlist为聚合入口,保证最终结果一定包含全部5门课程,不会因为学生未修读就缺失对应条目 $lookup阶段通过双条件匹配,仅查询当前学生对应课程的进度数据,避免拉取其他学生的冗余数据$unwind开启保留空值配置,未修读的课程不会被过滤$mergeObjects会自动合并两个对象的字段,进度记录存在时,学生姓名、完成日期、是否通过字段会自动追加到课程基础字段上,不存在则不会添加额外字段,完全匹配预期返回结构
内容的提问来源于stack exchange,提问作者zipzit
相关产品推荐
相关产品推荐

