如何用MongoDB聚合操作计算嵌套数组同类型分数的平均值?
MongoDB聚合实现按分数类型计算平均分并重组结构
可以通过以下聚合管道实现需求,核心思路是拆分分数数组、按类型分组计算平均分,再重组回目标结构:
完整聚合命令
db.students.aggregate([ // 拆分scores数组为单个文档,便于按type分组计算 { $unwind: "$scores" }, // 按学生标识和分数类型分组,直接计算平均分 { $group: { _id: { original_id: "$_id", student_id: "$student_id", class_id: "$class_id", type: "$scores.type" }, avgScore: { $avg: "$scores.score" } } }, // 重新按学生分组,将不同类型的平均分组装回scores数组 { $group: { _id: "$_id.original_id", student_id: { $first: "$_id.student_id" }, class_id: { $first: "$_id.class_id" }, scores: { $push: { type: "$_id.type", score: "$avgScore" } } } }, // 可选:格式化分数小数位数,匹配示例结果精度 { $set: { scores: { $map: { input: "$scores", as: "item", in: { type: "$$item.type", score: { $round: ["$$item.score", 10] } } } } } } ])
管道阶段说明
- $unwind:将每个学生的
scores数组拆分为独立文档,每个文档仅包含单个分数条目,为后续分组计算提供基础。 - $group(第一阶段):以学生原始
_id、student_id、class_id和分数type作为分组键,使用$avg直接计算该类型分数的平均值,无需手动计算总和与数量。 - $group(第二阶段):重新按学生原始
_id分组,通过$push将同一学生的不同类型平均分结果组装回scores数组,同时保留student_id和class_id字段。 - $set(可选):通过
$map遍历scores数组,用$round格式化分数的小数位数,确保输出结果与示例精度一致。
最终输出结果
运行上述命令后,将得到与目标结构完全匹配的文档:
{ _id: ObjectId("50b59cd75bed76f46522c34e"), student_id: 0, class_id: 2, scores: [ { type: 'exam', score: 57.9294711258 }, { type: 'quiz', score: 21.2454258821 }, { type: 'homework', score: 51.6520826017 } ] }
内容的提问来源于stack exchange,提问作者Aurell Layalia
相关产品推荐
相关产品推荐

