Node.js结合Mongoose使用MongoDB $in操作符查询返回空数组的问题
我帮你排查了几个关键问题,这些应该就是导致查询返回空数组的核心原因:
1. 查询日期范围与目标数据不匹配
看你提供的调用参数,查询的targetDate范围是2021-03-03 到 2021-03-31,但你给出的示例数据里targetDate是2021-04-06T14:30:00.000Z,这个日期完全不在你设定的查询区间内!这是最直接的原因——你的目标数据根本不在查询时间范围内,自然返回空数组。
解决方法:
检查调用参数里的fromTime和toTime是否正确,确保时间范围覆盖你要查询的数据日期。比如如果要包含示例数据的4月6日,需要把toTime调整到2021-04-07T18:29:59.000Z之后。
2. 错误使用Schema而非Model执行查询
在你的getGeofenceReport函数里,你写了:
GeofenceReportSchema.find(queryObj)
但GeofenceReportSchema是mongoose的Schema结构定义对象,不是可直接用于查询的模型实例。你应该使用你导出的model(也就是GeofenceReport)来调用find方法。
解决方法:
先确保已经正确导入模型:
const GeofenceReport = require('./path-to-your-model-file');
然后把查询代码改成:
GeofenceReport.find(queryObj)
3. IMEI的数组格式与类型优化
数组格式问题
你的调用参数里imei是单个数字866551038558000,如果queryItems.imei不是数组,$in操作符里就会传入单个值——虽然MongoDB允许这种写法,但为了避免潜在的类型错误,最好强制转换成数组:
const imeiList = Array.isArray(queryItems.imei) ? queryItems.imei : [queryItems.imei]; const queryObj = { $and: [ {targetDate: { $gte: new Date(queryItems.fromTime), $lte: new Date(queryItems.toTime)}}, {imei: {$in: imeiList}} ] };
数值精度问题
你的示例数据里IMEI存储的是$numberLong类型,而Mongoose模型里定义的是Number。虽然当前的IMEI数值小于JSNumber的最大安全值(2^53),但IMEI作为标识号不需要做数值运算,更稳妥的做法是把它定义为String类型:
imei: { type: String, required: true },
这样可以彻底避免数值转换带来的精度丢失或类型匹配问题,查询时也要确保传入的IMEI是字符串类型。
额外排查建议
- 查询前可以分别打印完整的
queryObj和数据里的targetDate、imei值,对比确认条件是否匹配; - 可以拆分查询条件,单独测试日期查询或IMEI查询,分步定位哪个条件出了问题。
内容的提问来源于stack exchange,提问作者Enihr

