MongoDB聚合:按班级、学生分组提取作业分数问题求助
解决MongoDB聚合按班级+学生分组保留作业分数的问题
你现在的问题出在分组的顺序和层级上——你直接按class_id做了一次分组,但没有先把同一个学生的作业分数合并到一起。咱们调整一下聚合管道的步骤,分两次分组就能完美达成你的需求:
修改后的聚合管道
[ // 展开scores数组,让每个分数成为独立文档 {'$unwind': {'path': '$scores'}}, // 筛选出仅homework类型的分数 {'$match': {'scores.type': 'homework'}}, // 第一步分组:按「班级ID+学生ID」组合分组,聚合当前学生的所有作业分数 { '$group': { '_id': { 'class_id': '$class_id', 'student_id': '$student_id' }, 'scores': {'$push': {'type': '$scores.type', 'score': '$scores.score'}} } }, // 第二步分组:按班级ID分组,聚合该班级下所有学生的作业分数信息 { '$group': { '_id': '$_id.class_id', 'all_scores': { '$push': { 'student_id': '$_id.student_id', 'scores': '$scores' } } } }, // 可选:重命名字段,让输出完全匹配你的期望格式 { '$project': { '_id': 0, 'class_id': '$_id', 'all_scores': 1 } } ]
步骤说明
$unwind+$match:和你原来的逻辑一致,先把嵌套的分数数组拆解开,只保留作业类型的分数文档。- 第一次
$group:用class_id和student_id的组合作为分组键,这样同一个班级里的同一个学生的所有作业分数会被收集到scores数组中,完成「按student_id合并分数」的核心需求。 - 第二次
$group:回到班级维度,把每个学生的信息(包含学生ID和对应的作业分数数组)聚合到all_scores数组里。 $project(可选):将默认的_id字段重命名为class_id,让最终输出格式和你期望的完全一致。
最终输出示例
执行上述管道后,你会得到这样的结果:
{ "class_id": 3, "all_scores": [ { "student_id": 110, "scores": [ {"type": "homework", "score": 89.98}, {"type": "homework", "score": 90.98} ] }, { "student_id": 190, "scores": [ {"type": "homework", "score": 18.98}, {"type": "homework", "score": 99.98} ] } ] }
内容的提问来源于stack exchange,提问作者Neel Patel
相关产品推荐
相关产品推荐

