简述MongoDB聚合?
参考回答
MongoDB 的聚合操作是一种强大的数据处理方式,用于对集合中的文档执行复杂的计算和转换。它通过 aggregate() 方法实现,可以完成分组、过滤、排序、计算等功能,类似于 SQL 中的 GROUP BY 和 HAVING。
聚合操作的核心是 聚合管道,它将多个数据处理阶段按顺序组合,每个阶段对输入数据进行操作,并将结果传递给下一个阶段。
详细讲解与拓展
1. 聚合的基本语法
db.collection.aggregate([ { stage1 }, { stage2 }, ... ])
每个 { stage } 表示一个数据处理阶段,常见的阶段包括:
– $match:过滤文档,相当于 SQL 中的 WHERE。
– $group:按字段分组并计算聚合结果,相当于 SQL 中的 GROUP BY。
– $project:指定返回字段,相当于 SQL 中的 SELECT。
– $sort:排序结果,相当于 SQL 中的 ORDER BY。
– $limit:限制结果数量,相当于 SQL 中的 LIMIT。
– $skip:跳过指定数量的文档,相当于分页操作。
2. 常见聚合阶段
$match:过滤文档- 用于筛选符合条件的文档,通常是聚合的第一阶段。
- 示例:查询年龄大于 30 的用户:
db.users.aggregate([ { match: { age: {gt: 30 } } } ])
$group:分组并计算- 用于将文档分组,并对每组数据进行统计或计算。
- 示例:按城市分组,并计算每个城市的用户数量:
db.users.aggregate([ { group: { _id: "city", count: { $sum: 1 } } } ])
$project:字段投影- 用于选择返回的字段,并支持对字段进行重命名或计算。
- 示例:只返回用户的名字和年龄:
db.users.aggregate([ { $project: { name: 1, age: 1, _id: 0 } } ])
$sort:排序- 用于对文档排序。
- 示例:按年龄降序排序:
db.users.aggregate([ { $sort: { age: -1 } } ])
$limit和$skip:分页- 示例:查询前 5 条记录:
db.users.aggregate([ { $limit: 5 } ])
- 示例:查询前 5 条记录:
3. 示例:综合应用
假设集合包含以下文档:
[
{ "name": "Alice", "age": 25, "city": "New York" },
{ "name": "Bob", "age": 30, "city": "Chicago" },
{ "name": "Charlie", "age": 35, "city": "New York" },
{ "name": "David", "age": 40, "city": "Chicago" }
]
需求:统计每个城市中年龄大于 30 的用户数量,并按数量降序排序。
聚合管道:
db.users.aggregate([
{ match: { age: {gt: 30 } } }, // 过滤年龄大于 30 的用户
{ group: { _id: "city", count: { sum: 1 } } }, // 按城市分组并统计数量
{sort: { count: -1 } } // 按数量降序排序
])
结果:
[
{ "_id": "Chicago", "count": 2 },
{ "_id": "New York", "count": 1 }
]
4. 常用聚合操作符
| 操作符 | 功能 | 示例 |
|---|---|---|
$sum |
求和 | { count: { $sum: 1 } } |
$avg |
平均值 | { avgAge: { avg: "age" } } |
$min |
最小值 | { minAge: { min: "age" } } |
$max |
最大值 | { maxAge: { max: "age" } } |
$push |
将字段值数组化 | { users: { push: "name" } } |
$first |
返回分组中的第一条记录 | { firstUser: { first: "name" } } |
$last |
返回分组中的最后一条记录 | { lastUser: { last: "name" } } |
5. 聚合性能优化
- 尽量使用索引:
- 在
$match阶段利用索引,可以显著提高性能。 - 示例:为
age字段创建索引:db.users.createIndex({ age: 1 })
- 在
- 限制返回数据量:
- 使用
$limit和$project限制返回字段和文档数量,减少内存使用。
- 使用
- 避免大数据排序:
- 如果可能,使用索引优化
$sort操作。
- 如果可能,使用索引优化
总结
MongoDB 的聚合操作通过 聚合管道 实现复杂的数据处理功能,包括筛选、分组、排序、计算等操作。常用阶段如 $match、$group、$project 等提供了丰富的功能,适用于各种统计和数据转换需求。在实际应用中,通过合理设计聚合管道和索引,可以显著提升查询性能和数据处理效率。