数据分组与统计($group、$sum、$avg等)
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
下一篇:多表关联($lookup)