MongoDB按日期实现每日累计求和的方案问询
MongoDB按日期实现每日累计求和的方案问询
看起来你是想实现每日累计净收入的计算——也就是当天的累计值等于当日收入加上之前所有日期的收入总和对吧?你的现有聚合逻辑里,最后计算的netIncome其实是所有日期的总收入,没有实现按日期逐步累加的效果,这就是问题所在。
我来帮你调整一下聚合管道,这里分两种情况给出方案,适配不同MongoDB版本:
方案一:MongoDB 5.0+ (推荐,用$setWindowFields更简洁高效)
这个版本新增的窗口函数专门用来处理这类累计计算,比嵌套分组+unwind的方式更直观:
db.collection.aggregate([ // 1. 筛选目标日期范围的数据 { $match: { date: { $gte: new Date("2023-05-31") } } }, // 2. 按天分组,计算单天的总收入(如果单天有多条记录的话) { $group: { _id: { $dateTrunc: { date: "$date", unit: "day" } }, // 把日期截断到天,确保同天记录合并 dailyIncome: { $sum: "$income" } } }, // 3. 按日期升序排序,保证累计顺序正确 { $sort: { _id: 1 } }, // 4. 核心:用窗口函数计算累计收入 { $setWindowFields: { partitionBy: null, // 不需要分组,所有数据在同一个窗口 sortBy: { _id: 1 }, // 按日期从早到晚排序 output: { netIncome: { $sum: "$dailyIncome", window: { documents: ["unbounded", "current"] } // 计算从第一条到当前文档的总和 } } } }, // 5. 整理输出字段,让结构更清晰 { $project: { _id: 0, date: "$_id", dailyIncome: 1, netIncome: 1 } } ])
方案二:MongoDB 5.0以下 (用$accumulator实现)
如果你的版本不支持窗口函数,可以用自定义累加器来实现累计:
db.collection.aggregate([ { $match: { date: { $gte: new Date("2023-05-31") } } }, { $group: { _id: { $dateTrunc: { date: "$date", unit: "day" } }, dailyIncome: { $sum: "$income" } } }, { $sort: { _id: 1 } }, { $group: { _id: null, data: { $push: { date: "$_id", dailyIncome: "$dailyIncome" } } } }, { $project: { data: { $accumulator: { init: function() { return { total: 0, items: [] }; }, accumulate: function(state, item) { state.total += item.dailyIncome; state.items.push({ date: item.date, dailyIncome: item.dailyIncome, netIncome: state.total }); return state; }, accumulateArgs: ["$$this"], merge: function(state1, state2) { state1.total += state2.total; state1.items = state1.items.concat(state2.items); return state1; }, finalize: function(state) { return state.items; }, lang: "js" } } } }, { $unwind: "$data" }, { $replaceRoot: { newRoot: "$data" } } ])
预期输出(和你给出的样本一致)
[ { "date": ISODate("2023-06-26T00:00:00Z"), "dailyIncome": 600, "netIncome": 600 }, { "date": ISODate("2023-06-27T00:00:00Z"), "dailyIncome": 400, "netIncome": 1000 }, { "date": ISODate("2023-06-28T00:00:00Z"), "dailyIncome": 200, "netIncome": 1200 }, { "date": ISODate("2023-06-29T00:00:00Z"), "dailyIncome": 300, "netIncome": 1500 }, { "date": ISODate("2023-06-30T00:00:00Z"), "dailyIncome": 500, "netIncome": 2000 } ]
备注:内容来源于stack exchange,提问作者Admonster Ad
相关产品推荐
相关产品推荐

