MongoDB聚合查询实现今日与昨日数据统计及增长率计算
MongoDB聚合查询实现今日与昨日数据统计及增长率计算
嗨,我来帮你搞定这个MongoDB聚合统计的需求!你想要在一次查询里拿到今日和昨日的记录数,进而计算增长率,这个完全可以通过MongoDB的聚合框架实现,我给你一步步拆解:
第一步:明确时间范围计算
首先得确定今日和昨日的时间边界,这里要注意MongoDB的ISODate是UTC时间,如果你的业务时区和UTC不同,记得调整偏移量。以你示例里的今日ISODate("2023-04-02T20:24:18.779Z")为例:
- 今日起始时间(startOfToday):
ISODate("2023-04-02T00:00:00.000Z") - 今日结束时间(endOfToday):
ISODate("2023-04-02T23:59:59.999Z") - 昨日起始时间(startOfYesterday):
ISODate("2023-04-01T00:00:00.000Z") - 昨日结束时间(endOfYesterday):
ISODate("2023-04-01T23:59:59.999Z")
你也可以用MongoDB的日期操作符在聚合内动态计算,比如用$currentDate获取当前时间,再用$dateTrunc截断到日期,然后加减一天来得到昨日的范围,这样就不用在应用层硬编码时间了。
第二步:编写聚合管道
我给你写一个完整的聚合查询,针对你的示例数据,运行后能直接拿到今日和昨日的统计数:
// 先在应用层计算时间范围(或者用聚合内动态计算) const today = new Date("2023-04-02T20:24:18.779Z"); const startOfToday = new Date(today.getFullYear(), today.getMonth(), today.getDate()); const endOfToday = new Date(startOfToday); endOfToday.setDate(endOfToday.getDate() + 1); const startOfYesterday = new Date(startOfToday); startOfYesterday.setDate(startOfYesterday.getDate() - 1); const endOfYesterday = startOfToday; // 聚合查询 db.collection.aggregate([ // 第一步:过滤出今日和昨日的数据,减少后续处理量 { $match: { created_at: { $gte: startOfYesterday, $lt: endOfToday // 用$lt代替$lte,避免边界时间重复统计 } } }, // 第二步:按日期分组,统计每日的记录数 { $group: { _id: { $dateToString: { format: "%Y-%m-%d", date: "$created_at" } }, count: { $sum: 1 } } }, // 第三步:把分组结果转成键值对,方便后续提取 { $project: { _id: 0, date: "$_id", count: 1 } }, // 第四步:将结果整理成包含today和yesterday的数组结构 { $group: { _id: null, createdAt: { $push: { $cond: [ { $eq: ["$date", startOfToday.toISOString().split('T')[0]] }, { today: "$count" }, { yesterday: "$count" } ] } } } }, // 可选:如果只需要统计结果,去掉_id字段 { $project: { _id: 0 } } ])
第三步:查询结果说明
针对你的示例数据,运行这个聚合后会得到你想要的结果:
{ "createdAt": [ { "today": 3 }, { "yesterday": 2 } ] }
如果你想把结果合并成单个对象方便取值,也可以把最后两个阶段替换成:
{ $group: { _id: null, today: { $max: { $cond: [{ $eq: ["$date", startOfToday.toISOString().split('T')[0]] }, "$count", 0] } }, yesterday: { $max: { $cond: [{ $eq: ["$date", startOfYesterday.toISOString().split('T')[0]] }, "$count", 0] } } } }, { $project: { _id: 0 } }
这样会得到更简洁的结构:
{ "today": 3, "yesterday": 2 }
第四步:计算增长率
拿到统计数后,你就可以直接计算增长率了,公式就是你提到的:
const growthRate = ((todayCount - yesterdayCount) / yesterdayCount) * 100;
⚠️ 注意:如果昨日的记录数是0,这里会出现除以0的错误,记得在代码里做判断处理哦!
额外小贴士
如果想在聚合内直接计算增长率,可以在最后加一个$project阶段:
{ $project: { today: 1, yesterday: 1, growthRate: { $cond: [ { $eq: ["$yesterday", 0] }, null, // 或者你想要的默认值,比如0或者"Infinite" { $multiply: [{ $divide: [{ $subtract: ["$today", "$yesterday"] }, "$yesterday"] }, 100] } ] } } }
这样就能直接在查询结果里拿到增长率啦!
备注:内容来源于stack exchange,提问作者Emmanuella
相关产品推荐
相关产品推荐

