MongoDB如何按日、周、月维度聚合统计门票售出数量
MongoDB 多维度门票销量统计方案
前置说明
建议优先将createdAt字段存储为MongoDB原生Date类型而非字符串,可大幅提升日期查询性能。如果当前确实是字符串类型,可参考下文特殊情况处理方案兼容。
以下示例以查询2021-11-08的销量为例,可直接替换查询日期参数复用。
完整聚合查询代码
// 定义查询目标日期,可按需修改 const targetDate = new Date("2021-11-08"); // 计算当日起止时间(零点到次日零点) const dayStart = new Date(targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate()); const dayEnd = new Date(dayStart.getTime() + 24 * 60 * 60 * 1000); // 计算当周起止时间(周一为周起始,周一零点到下周一零点) const dayOfWeek = targetDate.getDay() || 7; // 周日getDay返回0,统一转为7方便计算偏移量 const weekStart = new Date(dayStart.getTime() - (dayOfWeek - 1) * 24 * 60 * 60 * 1000); const weekEnd = new Date(weekStart.getTime() + 7 * 24 * 60 * 60 * 1000); // 计算当月起止时间(当月1号零点到下月1号零点) const monthStart = new Date(targetDate.getFullYear(), targetDate.getMonth(), 1); const monthEnd = new Date(targetDate.getFullYear(), targetDate.getMonth() + 1, 1); db.你的集合名.aggregate([ // 第一步:过滤当月所有数据,缩小计算范围,避免全表扫描提升性能 { $match: { createdAt: { $gte: monthStart, $lt: monthEnd } } }, // 第二步:单轮扫描统计三个维度的销量 { $group: { _id: null, // 统计当日销量 dayCount: { $sum: { $cond: [ { $and: [ { $gte: ["$createdAt", dayStart] }, { $lt: ["$createdAt", dayEnd] } ] }, 1, 0 ] } }, // 统计当周销量 weekCount: { $sum: { $cond: [ { $and: [ { $gte: ["$createdAt", weekStart] }, { $lt: ["$createdAt", weekEnd] } ] }, 1, 0 ] } }, // 统计当月销量 monthCount: { $sum: 1 } } }, // 第三步:格式化输出,去掉冗余字段 { $project: { _id: 0, 日: "$dayCount", 周: "$weekCount", 月: "$monthCount" } } ])
输出结果
针对你给出的示例数据,执行后输出如下:
{ "日" : 1, "周" : 1, "月" : 8 }
完全符合预期要求。
特殊情况处理:如果createdAt是字符串类型
只需在$match阶段之前增加一个字段转换阶段即可:
{ $addFields: { createdAt: { $toDate: "$createdAt" } } }
内容的提问来源于stack exchange,提问作者IT Forever
相关产品推荐
相关产品推荐

