第12章 MongoDB实战:一键洞察学生成绩全貌——聚合查询大显身手

2,193 阅读2分钟

任务描述

本任务旨在利用MongoDB的聚合表达式分析学生的成绩数据。我们将从students集合中提取有关每个学生的成绩统计信息,包括总分、平均分、最低分、最高分、所有成绩的列表、唯一的科目列表、最近一次的成绩和最早一次的成绩。这将有助于教育工作者和管理人员了解学生的学习情况。

任务准备

  1. 环境准备

    • 确保已安装MongoDB,并已启动MongoDB服务
    • 安装好Navicat Premium客户端工具
  2. 数据准备

    • 创建一个名为students的集合,并插入一些样本数据。每个文档应包含学生ID、姓名、科目、成绩和考试日期。 插入的样本数据:
db.students.insertMany([
  { studentId: ObjectId("1"), name: "学生A", subject: "数学", score: 85, examDate: ISODate("2024-05-01") },
  { studentId: ObjectId("1"), name: "学生A", subject: "英语", score: 78, examDate: ISODate("2024-04-20") },
  { studentId: ObjectId("2"), name: "学生B", subject: "数学", score: 92, examDate: ISODate("2024-05-01") },
  { studentId: ObjectId("2"), name: "学生B", subject: "英语", score: 88, examDate: ISODate("2024-04-15") },
  { studentId: ObjectId("1"), name: "学生A", subject: "数学", score: 90, examDate: ISODate("2024-04-25") },
  { studentId: ObjectId("2"), name: "学生B", subject: "科学", score: 95, examDate: ISODate("2024-03-30") }
]);

任务实施

  1. 执行MongoDB的聚合查询,提取学生成绩的相关信息。
db.students.aggregate([
  {
    $sort: { examDate: 1 } // 先按考试日期升序排序
  },
  {
    $group: {
      _id: "$studentId",
      name: { $first: "$name" },                     // 学生姓名
      totalScore: { $sum: "$score" },                // 总分
      averageScore: { $avg: "$score" },              // 平均分
      minScore: { $min: "$score" },                  // 最低分
      maxScore: { $max: "$score" },                  // 最高分
      allScores: { $push: "$score" },                // 所有成绩的列表
      uniqueSubjects: { $addToSet: "$subject" },     // 唯一科目列表
      firstScore: { $first: "$score" },              // 最早一次成绩
      lastScore: { $last: "$score" }                 // 最近一次成绩
    }
  }
]);

2. 查询分析

排序阶段:首先使用$sort阶段按examDate字段升序排列学生的成绩,这样在后面分组时,最早的成绩会在前面,最近的成绩会在最后。

聚合阶段:在$group阶段使用$first$last来分别获取最早和最近的成绩。这里不需要对这两个操作再进行排序。

预期输出

image.png

实验实训

小任务1:科目成绩分布

编写一个聚合查询,展示每个科目中所有学生的成绩分布。结果应该包括每个科目的名称以及该科目下的所有成绩。

预期输出:

每个科目名称 对应科目的所有成绩列表 SQL风格的查询语句示例:

SELECT subject, GROUP_CONCAT(score ORDER BY score SEPARATOR ', ') AS scores FROM students GROUP BY subject;

MongoDB聚合查询:

db.students.aggregate([
  {
    $group: {
      _id: "$subject",
      scores: { $push: "$score" }
    }
  }
]);

小任务2:成绩频率统计

编写一个聚合查询,统计每个分数段的学生数量。可以将成绩分为不同的区间,比如小于60分、60-70分、70-80分、80-90分、大于90分。

预期输出:

成绩区间 对应区间的学生数 MongoDB聚合查询:

db.students.aggregate([
  {
    $bucket: {
      groupBy: "$score",
      boundaries: [0, 60, 70, 80, 90, 100],
      default: "other",
      output: {
        count: { $sum: 1 }
      }
    }
  }
]);

小任务3:科目成绩排名

编写一个聚合查询,找出每个科目中成绩最高的前三名学生。结果应该包括学生的姓名、科目以及对应的分数。

预期输出:

学生姓名 科目 分数 MongoDB聚合查询:

db.students.aggregate([
  {
    $group: {
      _id: "$subject",
      students: { $push: { name: "$name", score: "$score" } }
    }
  },
  {
    $project: {
      _id: 0,
      subject: "$_id",
      topStudents: {
        $slice: ["$students", 3]
      }
    }
  },
  {
    $unwind: "$topStudents"
  },
  {
    $sort: { "topStudents.score": -1 }
  }
]);

小任务4:科目平均成绩

编写一个聚合查询,计算每个科目的平均成绩。结果应该包括每个科目的名称以及该科目的平均成绩。

预期输出:

科目名称 平均成绩 MongoDB聚合查询:

db.students.aggregate([
  {
    $group: {
      _id: "$subject",
      averageScore: { $avg: "$score" }
    }
  }
]);

通过这些小任务,您可以加深对MongoDB聚合框架的理解,并学会如何利用不同的聚合操作来分析复杂的数据集。