您的位置:

MongoDB分组查询(mongogroupby)

在开发中,我们常常需要对某个集合内的数据进行聚合操作或统计分析。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等)结合使用,以实现更复杂的数据处理需求。