MongoDB中查询每日19:01-06:59时段ISODate类型数据的聚合查询无结果问题排查
解决MongoDB聚合查询无结果的问题
我来帮你排查下问题所在,你之所以查不到任何结果,核心是$match阶段的逻辑错误,咱们一步步来修正:
问题出在哪?
你当前的匹配条件是:
{ $match: { 'minutes' : { $gt : 19 * 60, $lt : 7 * 60 } } }
这个条件要求minutes(转换后的分钟数)同时大于1140(对应19:00)且小于420(对应07:00)——这在逻辑上根本不可能成立,自然返回空结果。
你的目标时间范围是19:01 - 06:59,这其实是两个独立的区间:
- 晚上19:01 到 23:59(分钟数 > 1140)
- 凌晨00:00 到 06:59(分钟数 < 420)
必须用$or来组合这两个条件才能覆盖目标范围。
修正后的完整查询
另外,给你个性能优化建议:把$match阶段放到最前面,先过滤掉不需要的数据,这样后续的投影、分组操作处理的数据量会小很多,查询速度更快。修正后的代码如下:
db.Steps.aggregate([ // 第一步:先过滤符合时间范围的文档 { $match: { $or: [ { $expr: { $gt: [ { $add: [ { $multiply: [ { $hour: '$dateTime' }, 60 ] }, { $minute: '$dateTime' } ] }, 19 * 60 ] } }, { $expr: { $lt: [ { $add: [ { $multiply: [ { $hour: '$dateTime' }, 60 ] }, { $minute: '$dateTime' } ] }, 7 * 60 ] } } ] } }, // 第二步:投影需要的字段 { $project:{ byDay: {$dayOfMonth: {date: "$dateTime"}}, byMonth: {$month: {date: "$dateTime"}}, _id: 0, val: {$toInt: "$value"} } }, // 第三步:按月份和日期分组,计算步数平均值 { $group:{ _id: {month: "$byMonth", day: "$byDay"}, StepsDone: {$avg: "$val"} } }, // 第四步:按日期排序 { $sort: {_id: 1} } ]);
更简洁的时间判断方式
如果不需要严格卡到分钟(比如允许包含19:00整的文档),你也可以直接用$hour来判断,逻辑更直观:
db.Steps.aggregate([ { $match: { $or: [ { $expr: { $gt: [ { $hour: '$dateTime' }, 19 ] } }, // 小时大于19,也就是20:00及之后 { $expr: { $lt: [ { $hour: '$dateTime' }, 7 ] } } // 小时小于7,也就是00:00到06:59 ] } }, // 后续的投影、分组、排序和上面一致 { $project:{ byDay: {$dayOfMonth: {date: "$dateTime"}}, byMonth: {$month: {date: "$dateTime"}}, _id: 0, val: {$toInt: "$value"} } }, { $group:{ _id: {month: "$byMonth", day: "$byDay"}, StepsDone: {$avg: "$val"} } }, { $sort: {_id: 1} } ]);
要是你必须严格排除19:00整的记录,那还是用分钟数的判断方式更准确。
内容的提问来源于stack exchange,提问作者readymade
相关产品推荐
相关产品推荐

