阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 数据分组与统计($group、$sum、$avg等)

数据分组与统计($group、$sum、$avg等)

作者:陈川 阅读数:31160人阅读 分类: MongoDB

MongoDB的聚合框架提供了强大的数据处理能力,其中$group阶段是核心操作之一,结合$sum$avg等累加器可以实现复杂的数据分组与统计。通过灵活组合这些操作符,能够高效完成数据汇总、平均值计算、最大值提取等常见分析需求。

数据分组基础($group)

$group阶段通过指定_id字段定义分组依据,将输入文档按该字段值分组。分组后可以使用累加器对每组文档进行统计计算。例如,按城市分组并统计每个城市的文档数量:

db.sales.aggregate([
  {
    $group: {
      _id: "$city",
      count: { $sum: 1 }
    }
  }
])

此操作会输出类似结果:

{ "_id" : "北京", "count" : 42 }
{ "_id" : "上海", "count" : 38 }

常用累加器操作符

求和计算($sum)

$sum支持数值累加,既可统计文档数量(传常量1),也可对指定字段求和:

// 按产品类别统计销售总额
db.orders.aggregate([
  {
    $group: {
      _id: "$category",
      totalSales: { $sum: "$amount" },
      orderCount: { $sum: 1 }
    }
  }
])

平均值计算($avg)

计算分组内数值字段的平均值时会自动忽略非数值类型:

// 计算各部门员工平均工资
db.employees.aggregate([
  {
    $group: {
      _id: "$department",
      avgSalary: { $avg: "$salary" }
    }
  }
])

极值获取($max/$min)

获取分组中的极值时,日期、字符串等类型也可比较:

// 找出各商品的最早销售记录
db.sales.aggregate([
  {
    $group: {
      _id: "$productId",
      firstSaleDate: { $min: "$saleDate" }
    }
  }
])

复合分组与高级用法

多字段分组

_id可接受对象实现多级分组,例如按年月统计:

db.orders.aggregate([
  {
    $group: {
      _id: {
        year: { $year: "$orderDate" },
        month: { $month: "$orderDate" }
      },
      total: { $sum: "$amount" }
    }
  }
])

数组操作($push/$addToSet)

收集分组中的特定字段值,$addToSet会自动去重:

// 收集每个客户购买过的商品ID
db.orders.aggregate([
  {
    $group: {
      _id: "$customerId",
      purchasedItems: { $addToSet: "$productId" }
    }
  }
])

性能优化实践

索引利用策略

$group前使用$match$sort阶段时,确保这些操作能命中索引:

db.sales.aggregate([
  { $match: { status: "completed" } },  // 使用status索引
  { $sort: { productId: 1 } },         // 使用productId索引
  {
    $group: {
      _id: "$productId",
      total: { $sum: "$quantity" }
    }
  }
])

内存控制

处理大型集合时可能需要增加allowDiskUse选项:

db.largeCollection.aggregate(
  [/* 管道操作 */],
  { allowDiskUse: true }
)

实际业务场景示例

电商数据分析

统计每个用户最近3个月的消费频次与平均客单价:

db.orders.aggregate([
  {
    $match: {
      orderDate: { $gte: new Date("2023-01-01") }
    }
  },
  {
    $group: {
      _id: "$userId",
      orderCount: { $sum: 1 },
      avgAmount: { $avg: "$total" },
      lastPurchase: { $max: "$orderDate" }
    }
  },
  {
    $project: {
      userId: "$_id",
      _id: 0,
      orderCount: 1,
      avgAmount: { $round: ["$avgAmount", 2] },
      daysSinceLastPurchase: {
        $divide: [
          { $subtract: [new Date(), "$lastPurchase"] },
          86400000
        ]
      }
    }
  }
])

物联网设备监控

计算每台设备每小时的平均传感器读数:

db.sensorReadings.aggregate([
  {
    $project: {
      deviceId: 1,
      value: 1,
      hour: { $hour: "$timestamp" }
    }
  },
  {
    $group: {
      _id: {
        device: "$deviceId",
        hour: "$hour"
      },
      avgValue: { $avg: "$value" },
      minValue: { $min: "$value" },
      maxValue: { $max: "$value" }
    }
  }
])

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌