Skip to content

MongoDB 聚合

MongoDB 提供了强大的聚合框架,允许我们对数据进行复杂的查询和分析操作。聚合操作可以帮助我们计算统计数据、分组数据、排序数据等。

基本概念

聚合管道

MongoDB 的聚合操作使用管道(Pipeline)模式。数据会经过一系列的阶段(Stage)处理,每个阶段都会对数据进行一些操作,最终输出我们需要的结果。

常见的聚合阶段

  1. $match:用于筛选文档
  2. $group:用于分组文档
  3. $sort:用于排序文档
  4. $limit:用于限制返回的文档数量
  5. $skip:用于跳过指定数量的文档
  6. $project:用于投影字段
  7. $unwind:用于展开数组字段
  8. $lookup:用于关联查询

基本聚合操作

使用 $match 和 $group 阶段

javascript
// 统计每个状态的用户数量
db.users.aggregate([
  { $match: { status: { $in: ["active", "pending", "inactive"] } } },
  { $group: { _id: "$status", count: { $sum: 1 } } },
  { $sort: { count: -1 } }
])

使用 $project 阶段

javascript
// 计算用户的全名和年龄,只返回特定字段
db.users.aggregate([
  {
    $project: {
      fullName: { $concat: ["$firstName", " ", "$lastName"] },
      age: 1,
      email: 1,
      _id: 0
    }
  }
])

使用 $unwind 阶段

javascript
// 展开 tags 数组字段
db.users.aggregate([
  { $unwind: "$tags" }
])

使用 $lookup 阶段

javascript
// 关联查询用户和他们的订单
db.users.aggregate([
  {
    $lookup: {
      from: "orders",
      localField: "_id",
      foreignField: "userId",
      as: "orders"
    }
  }
])

常见的聚合操作符

数学操作符

  1. $sum:计算总和
  2. $avg:计算平均值
  3. $min:计算最小值
  4. $max:计算最大值
  5. $push:将值添加到数组中
  6. $addToSet:将值添加到数组中,并确保值唯一

字符串操作符

  1. $concat:连接字符串
  2. $toUpper:将字符串转换为大写
  3. $toLower:将字符串转换为小写
  4. $substr:截取字符串的一部分

日期操作符

  1. $year:提取年份
  2. $month:提取月份
  3. $dayOfMonth:提取日期
  4. $hour:提取小时
  5. $minute:提取分钟
  6. $second:提取秒

聚合操作的优化

管道操作的顺序

在使用聚合操作时,我们应该注意操作的顺序。通常,我们应该将筛选操作放在前面,以便在数据量较小的情况下进行后续操作。

使用索引

在使用 $match$sort 阶段时,我们应该确保这些阶段使用了适当的索引,以提高查询性能。

限制返回的数据量

我们可以使用 $limit$skip 阶段来限制返回的数据量,从而减少网络传输和客户端的内存使用。

与 MapReduce 比较

虽然 MongoDB 提供了 MapReduce 功能,但在大多数情况下,聚合框架的性能更好,更易于使用。因此,我们应该优先使用聚合框架,而不是 MapReduce。

性能考虑

  1. 数据量:聚合操作的性能取决于数据量的大小。对于大型数据集,聚合操作可能需要较长的时间。
  2. 索引的使用:为查询字段和排序字段创建适当的索引可以提高查询性能。
  3. 内存限制:聚合操作有一个默认的内存限制(100MB)。如果聚合操作需要的内存超过这个限制,MongoDB 会将数据转移到磁盘上,这会导致性能下降。

总结

MongoDB 的聚合框架是一个强大的查询和分析工具,它允许我们对数据进行复杂的操作。通过使用不同的聚合阶段和操作符,我们可以实现各种查询需求。在使用聚合操作时,我们需要注意操作的顺序、索引的使用和性能优化,以确保查询的高效执行。seed:tool_call