如何在MongoDB中实现多字段分组并计算平均值?
MongoDB聚合查询:按学生和科目计算平均分
我来帮你搞定这个需求!根据你提供的样本数据和期望输出,我们可以通过MongoDB的聚合框架完成按name和sub分组计算平均分,并整理成目标结构的操作。
完整聚合查询代码
db.student.aggregate([ // 第一阶段:按学生姓名+科目分组,计算每门科目的平均分 { $group: { _id: { name: "$name", sub: "$sub" }, avgMarks: { $avg: "$marks" } } }, // 第二阶段:按学生姓名分组,将该学生的所有科目平均分整理为数组 { $group: { _id: "$_id.name", subjects: { $push: { sub: "$_id.sub", avgMarks: "$avgMarks" } } } }, // 可选:调整输出字段(这里保持默认即可,若需重命名可修改) { $project: { _id: 1, subjects: 1 } } ])
各阶段详细说明
第一个
$group阶段:
我们以name(学生姓名)和sub(科目)的组合作为分组键,用$avg运算符直接计算该分组下的平均分。这一步会生成每个学生每门科目的单独平均分记录。第二个
$group阶段:
以学生姓名作为分组键,通过$push运算符把同一学生的所有科目平均分数据合并到一个数组里。这一步把分散的科目记录聚合为每个学生的统一条目。$project阶段:
可选的格式调整阶段,这里我们保留_id(学生姓名)和subjects(科目平均分数组),确保输出结构简洁清晰,符合MongoDB的BSON文档规范。
查询结果示例
运行上述查询后,你会得到如下结果(和你期望的输出几乎一致,仅多了合法的数组键名subjects——因为MongoDB要求所有顶层元素都是键值对,不能直接放置无键名数组):
[ { "_id": "Vikash", "subjects": [ { "sub": "Physics", "avgMarks": 15 }, { "sub": "Math", "avgMarks": 25 } ] }, { "_id": "Raj", "subjects": [ { "sub": "Physics", "avgMarks": 22.5 }, { "sub": "Math", "avgMarks": 15 } ] } ]
如果需要在客户端进一步调整为你期望的无键名数组格式,可以在获取数据后做简单处理(比如提取subjects数组作为顶层元素,但注意这不符合JSON/BSON规范,仅适合特定展示场景)。
内容的提问来源于stack exchange,提问作者Kundan
相关产品推荐
相关产品推荐

