MongoDB如何查询过去12个月各月累计店铺总数
MongoDB 过去12个月各月累计店铺数查询实现方案
集合样本结构
{ _id: '5f3d4e5e01e06f0007335233', name: 'Walmart', createdAt: '2020-08-22T17:42:09.908+00:00' }
现有查询能力
你当前的聚合查询已经可以获取过去12个月每月的新增店铺数量:
Shop.aggregate([{ $match: { createdAt: { $gte: { $date: {{moment.utc().subtract(12, "months").startOf('day').toISOString()}} }, $lt: { $date: {{moment.utc().startOf('day').toISOString()}} } } } }, { $project: { dateParts: { $dateToParts: { date: '$createdAt' } }, total: true, } }, { $group: { _id: { month: '$dateParts.month', year: '$dateParts.year', }, numShops: { $sum: 1 }, } }])
现有查询仅返回单月新增数据,格式如下:
[{ _id: { month:3, year:2021 }, numShops:62, }, ... ]
调整后实现累计统计的查询方案
你需要在现有聚合管道基础上新增排序、累计求和、日期格式化三个阶段即可,完整语句如下:
Shop.aggregate([ // 原有匹配阶段:过滤过去12个月的店铺数据 { $match: { createdAt: { $gte: { $date: {{moment.utc().subtract(12, "months").startOf('day').toISOString()}} }, $lt: { $date: {{moment.utc().startOf('day').toISOString()}} } } } }, // 原有日期拆分阶段 { $project: { dateParts: { $dateToParts: { date: '$createdAt' } } } }, // 原有分组阶段:统计每月新增店铺数 { $group: { _id: { month: '$dateParts.month', year: '$dateParts.year', }, monthlyNew: { $sum: 1 }, } }, // 新增1:按年月正序排序,保证累加顺序正确 { $sort: { "_id.year": 1, "_id.month": 1 } }, // 新增2:窗口函数实现累计求和 { $setWindowFields: { sortBy: { "_id.year": 1, "_id.month": 1 }, output: { numShops: { $sum: "$monthlyNew", window: { documents: ["unbounded", "current"] } } } } }, // 新增3:格式化日期为 月-年 格式,调整返回字段结构 { $project: { _id: 0, date: { $dateToString: { format: "%b-%Y", date: { $dateFromParts: { year: "$_id.year", month: "$_id.month", day: 1 } } } }, numShops: 1 } } ])
结果说明
最终返回格式完全符合预期:
[ { "date": "Aug-2020", "numShops": 100 }, { "date": "Sep-2020", "numShops": 230 }, ... ]
注意事项
$setWindowFields是MongoDB 5.0版本推出的功能,如果你使用的是更早版本,可以在查询拿到每月新增数据后,在业务代码层做累加计算,逻辑完全一致。- 如果需要统计全历史累计(不是仅过去12个月的新增累加),可以把
$match的时间范围下限去掉,匹配所有创建时间小于当前的店铺即可。
内容的提问来源于stack exchange,提问作者Umair Khalid
相关产品推荐
相关产品推荐

