MongoDB聚合问题:按studentType求考试平均分返回null
解决MongoDB聚合查询中exam分数平均值返回null的问题
嘿,我来帮你搞定这个问题!你现在得到AverageMarks: null的结果,核心原因是依赖数组索引来获取exam分数的方式不可靠——你默认scores数组的第一个元素就是exam类型,但实际数据里,不同文档的scores数组元素顺序可能不一样,导致很多文档取不到有效的exam分数,最终$avg因为没有可用的有效值,只能返回null。
正确的解法有两种,你可以根据场景选择:
方法1:用$filter筛选指定类型的分数(不展开数组)
这种方法不需要展开数组,直接在$project阶段筛选出type为exam的分数项,再提取分数值:
db.student.aggregate([ { $project: { _id: 0, studentType: 1, examScore: { // 先筛选出type为exam的分数项 $arrayElemAt: [ { $filter: { input: "$scores", cond: { $eq: ["$$this.type", "exam"] } } }, 0 // 取筛选后的第一个元素(每个学生只有一个exam分数) ] } } }, { $group: { _id: "$studentType", AverageMarks: { $avg: "$examScore.score" } } } ])
方法2:用$unwind展开数组后匹配筛选(更直观)
如果数据量不是特别大,这种方法更容易理解:先展开scores数组,只保留exam类型的分数记录,再按studentType分组计算平均值:
db.student.aggregate([ { $unwind: "$scores" }, // 展开scores数组,每条分数单独成文档 { $match: { "scores.type": "exam" } }, // 只保留exam类型的分数 { $group: { _id: "$studentType", AverageMarks: { $avg: "$scores.score" } } } ])
为什么原来的查询会失败?
你原来的"scores.0.score"是取数组的第一个元素的score,但如果某个学生的scores数组第一个元素是quiz或者homework,那这个值就不是你要的exam分数,甚至可能不存在,导致$avg计算时没有有效数据,最终返回null。
内容的提问来源于stack exchange,提问作者Negi007
相关产品推荐
相关产品推荐

