在 MongoDB 聚合中添加缺失的日期
Posted
技术标签:
【中文标题】在 MongoDB 聚合中添加缺失的日期【英文标题】:Adding Missing Dates in MongoDB Aggregation 【发布时间】:2020-09-16 10:56:38 【问题描述】:在这个问题中,我想获取以下时间范围的用户订阅
今天 本周 本月 今年对于这个时间范围,我想显示所有可能日期的$group
。
[
Dates: '2020-05-21', Count: 3, AverageIncome: 30 ,
Dates: '2020-05-22', Count: 10, AverageIncome: 30 ,
Dates: '2020-05-24', Count: 1, AverageIncome: 37 ,
Dates: '2020-05-25', Count: 1, AverageIncome: 30 ,
Dates: '2020-05-26', Count: 2, AverageIncome: 65
]
我想添加缺失的日期以及将累加器数据设置为 0。例如,它应该是
[
Dates: '2020-05-21', Count: 3, AverageIncome: 30 ,
Dates: '2020-05-22', Count: 10, AverageIncome: 30 ,
Dates: '2020-05-23', Count: 0, AverageIncome: 0 ,
Dates: '2020-05-24', Count: 1, AverageIncome: 37 ,
Dates: '2020-05-25', Count: 1, AverageIncome: 30 ,
Dates: '2020-05-26', Count: 2, AverageIncome: 65 ,
Dates: '2020-05-27', Count: 0, AverageIncome: 0 ,
Dates: '2020-05-28', Count: 2, AverageIncome: 0 ,
]
PS:此时UTC时间为5月28日晚上11点45分
我正在使用的聚合管道阶段
const $agg = await Subscription.aggregate([
$match:
createdOn:
$gte: moment(req.query.from).toDate(),
$lte: moment(req.query.to).toDate()
,
isCancelled: false
,
$group:
_id:
$dateToString:
format: "%Y-%m-%d",
date: "$createdOn"
,
count: $sum: 1 ,
avgAmount: $avg: "$amountPaid"
,
$project:
_id: false,
sortKey:
$dateFromString:
dateString: "$_id"
,
Dates: "$_id",
Count: "$count",
AverageIncome: "$avgAmount"
,
$sort:
sortKey: 1
,
$project:
sortKey: false
]);
【问题讨论】:
【参考方案1】:前段时间我遇到过类似的问题,这是我遵循的方法:
function fillEmptyDates($agg, $defaultData, from, to)
const $aggObj = ; //Taking this as an object for easy checking
$agg.map((agg) =>
$aggObj[agg.Date] = agg; //Making an object from array entries with Date as key
);
const $loopDate = moment(from);
const $endDate = moment(to);
//Starting from from date to to date, checking if any date does not have entry in $aggObje
while ($endDate.isSameOrAfter($loopDate))
let $aggDate = $loopDate.format("YYYY-MM-DD");
if (!$aggObj.hasOwnProperty($aggDate))
//If any date does not have entry, creating a new entry from default aggregates and giving it the date as current date
$aggObj[$aggDate] =
...$defaultData,
Date: $aggDate
;
$loopDate.add(1, "day"); //Incrementing aggregate date
//Converting back to array and sorting by date
return Object.values($aggObj).sort((a, b) =>
moment(a.Date).isBefore(moment(b.Date)) ? -1 : 1
);
;
//You can call this function like so
$agg = fillEmptyDates(
$agg,
Count: 0, AverageIncome: 0 ,
req.query.from,
req.query.to,
)
【讨论】:
这是一个非常有用的答案,非常感谢以上是关于在 MongoDB 聚合中添加缺失的日期的主要内容,如果未能解决你的问题,请参考以下文章
使用 mongodb 聚合管道按升序向集合中的所有记录添加日期