使用Mongoose Aggregate统计当月数据无匹配结果问题求助
问题解决:Mongoose聚合查询当月数据无匹配结果
问题根源
你代码里的start和end变量是通过setHours()返回的时间戳(数字类型),而MongoDB中createdAt字段通常存储为Date类型。虽然Mongo Playground支持时间戳与Date的比较,但Mongoose在聚合管道的类型处理上存在隐性差异,或是客户端与数据库时区不一致,导致过滤条件失效。
修复方案
方案1:直接使用Date对象(推荐)
避免将Date转换为时间戳,直接构造起止日期的Date实例:
const now = new Date(); const year = now.getFullYear(); const month = now.getMonth(); // 当月第一天 00:00:01 const start = new Date(year, month, 1, 0, 0, 1); // 当月最后一天 23:59:59 const end = new Date(year, month + 1, 0, 23, 59, 59); const data = await verificationModel.aggregate([ { $match: { 'status': { $gt: 3, $lt:7 }, 'createdAt': { $gt: start, $lt: end }, 'fename': { $ne: null } } }, { $facet: { "categorizedBycasecount": [ { $unwind: "$fename" }, { $sortByCount: "$fename" }, { $limit:5 } ] } } ]);
方案2:使用MongoDB内置日期操作符(解决时区问题)
如果客户端与数据库时区不一致,直接在聚合管道中用$dateFromParts生成数据库时区的起止日期:
const now = new Date(); const year = now.getFullYear(); const month = now.getMonth(); const data = await verificationModel.aggregate([ { $match: { 'status': { $gt: 3, $lt:7 }, 'fename': { $ne: null }, $expr: { $and: [ { $gte: ['$createdAt', { $dateFromParts: { year: year, month: month + 1, day: 1, hour: 0, minute: 0, second: 1 } }] }, { $lte: ['$createdAt', { $dateFromParts: { year: year, month: month + 1, day: { $dayOfMonth: { $dateFromParts: { year: year, month: month + 1, day: 1 } } }, hour:23, minute:59, second:59 } }] } ] } } }, { $facet: { "categorizedBycasecount": [ { $unwind: "$fename" }, { $sortByCount: "$fename" }, { $limit:5 } ] } } ]);
说明
- 方案1适用于客户端与数据库时区一致的场景,代码更简洁。
- 方案2通过MongoDB内置函数生成日期,避免时区偏差,适合分布式部署或跨时区场景。
内容的提问来源于stack exchange,提问作者Ankit Patel
相关产品推荐
相关产品推荐

