在开发中,我们常常需要对某个集合内的数据进行聚合操作或统计分析。MongoDB提供了丰富的聚合操作函数,其中分组查询是其中最常用也是最重要的一个操作。
一、基本概念
所谓分组,就是将相同的数据按照指定的字段进行归类,然后进行聚合操作。以学生数据为例,我们可以按照学生的年级字段进行分组,然后统计每个年级的学生人数、平均分等信息。
db.student.aggregate([ { $group: { _id: "$grade", //按照年级字段分组 count: { $sum: 1 } //计算每组的学生数量 } } ])
上面的代码通过aggregate函数实现了分组查询,首先指定了要分组的字段,这里是grade字段。然后定义了要统计的信息,这里仅统计每组的学生数量。
二、基本操作符
1、$sum
$sum用于计算指定字段的总和,仅能用于数值类型字段。例如,统计每个年级的总分数:
db.student.aggregate([ { $group: { _id: "$grade", totalScore: { $sum: "$score" } //计算每组的总分数 } } ])
2、$avg
$avg用于计算指定字段的平均值,仅能用于数值类型字段。例如,统计每个年级的平均分数:
db.student.aggregate([ { $group: { _id: "$grade", avgScore: { $avg: "$score" } //计算每组的平均分数 } } ])
3、$min
$min用于求指定字段的最小值。例如,统计每个年级的最低分数:
db.student.aggregate([ { $group: { _id: "$grade", minScore: { $min: "$score" } //计算每组的最低分数 } } ])
4、$max
$max用于求指定字段的最大值。例如,统计每个年级的最高分数:
db.student.aggregate([ { $group: { _id: "$grade", maxScore: { $max: "$score" } //计算每组的最高分数 } } ])
三、进阶操作符
1、$push
$push用于将指定字段的值插入一个数组中,可以用于统计每组包含哪些学生的数据。例如:
db.student.aggregate([ { $group: { _id: "$grade", students: { $push: "$name" } //将每组的学生姓名插入数组中 } } ])
执行结果中,每个年级的结果中都包含了一个数组,在数组中保存了该年级的所有学生的姓名。
2、$addToSet
$addToSet也用于将指定字段的值插入一个数组中,但与$push不同的是,$addToSet保证数组中的元素不重复。例如:
db.student.aggregate([ { $group: { _id: "$grade", subjects: { $addToSet: "$subject" } //将每组的课程名称插入数组中 } } ])
执行结果中,每个年级的结果中都包含了一个数组,在数组中保存了该年级包含的所有课程名称,且不重复。
3、$first、$last
$first和$last分别用于在每个分组中,获取某个指定字段的第一个和最后一个值。例如,统计每个年级第一名和最后一名的成绩:
db.student.aggregate([ { $group: { _id: "$grade", firstScore: { $first: "$score" }, //每组的第一名成绩 lastScore: { $last: "$score" } //每组的最后一名成绩 } } ])
四、多字段分组
除了按照单个字段进行分组外,还可以按照多个字段进行分组。例如,统计每个年级每门课程的平均成绩:
db.student.aggregate([ { $group: { _id: { grade: "$grade", subject: "$subject" }, //按照多个字段分组 avgScore: { $avg: "$score" } //计算每组的平均分数 } } ])
首先定义了_id字段,该字段同时包含了grade和subject字段。然后再定义了要统计的信息,这里是每组的平均分数。
五、分组操作前的过滤
在进行分组查询前,我们可以通过$match操作符对原始数据进行过滤,只保留符合条件的数据。
db.student.aggregate([ { $match: { subject: "Math" } //筛选出课程为Math的数据 }, { $group: { _id: "$grade", //按照年级字段分组 count: { $sum: 1 } //计算每组的学生数量 } } ])
上述代码先通过$match操作符,筛选出了课程为Math的数据,然后再进行分组查询。
六、总结
分组查询是MongoDB中最常用也是最重要的操作之一,通过使用丰富的操作符,我们可以对原始数据进行灵活的聚合操作和统计分析。在实际使用中,我们通常会将分组查询与其他操作符(如$project、$sort等)结合使用,以实现更复杂的数据处理需求。