npm mongodb模块$where查询结果异常,与mongosh表现不一致求助
问题
我是MongoDB新手,我的应用基于Node.js、Express和MongoDB开发,使用npm的mongodb模块从后端连接并操作数据库。我向products集合插入了以下文档:
async function insert (collection){ const now = new Date() now.setFullYear(now.getFullYear()+2000) const data = await collection.insertMany([ { title: "banana", exp:now}, { title: "icecream", exp:now}, { title: "bread", exp:now}, ]); return data; }
插入后集合中的数据如截图所示。但当我使用$where运算符在find方法中查询所有已过期的产品时,却得到了所有未过期的产品,查询代码如下:
async function find(collection){ const now = new Date() console.log('at now: ',now) const data = await collection.find({ $where: function () { return this.exp < new Date(); }, }).toArray() return data; }
得到的输出不符合预期。而我使用mongosh(Mongo Shell)测试相同查询时,返回的是空数组(符合预期):
>db.product.find({ $where: function () { return this.exp < new Date(); } }).toArray() []
请问此处出现了什么问题,该如何修复?
问题原因
$where函数的执行环境差异:
在Node.js的mongodb驱动中,传递给$where的函数会被序列化为字符串发送到MongoDB服务器执行。虽然代码和mongosh中一致,但服务器端执行new Date()生成的时间可能和客户端本地时间存在差异,或者this.exp在服务器JS环境中的类型转换出现异常,导致对比逻辑反向。$where本身的缺陷:$where依赖MongoDB服务器的JS引擎执行代码,性能远低于标准查询运算符,还存在注入风险,完全不适合做简单的日期对比查询。
修复方案
直接使用MongoDB标准的$lt比较运算符替代$where,在客户端生成当前时间作为查询条件,彻底规避执行环境差异问题,同时提升查询性能:
async function find(collection){ const now = new Date() console.log('at now: ',now) // 使用$lt运算符替代$where,直接对比日期字段 const data = await collection.find({ exp: { $lt: now } }).toArray() return data; }
额外说明
- 插入数据时,Node.js的
Date对象会自动转换为MongoDB的BSON Date类型存储,查询时直接用客户端生成的Date对象对比即可,MongoDB会自动处理类型匹配。 - 永远优先使用标准查询运算符(如
$lt、$gt、$eq等),仅在处理极复杂的自定义逻辑时才考虑$where。
内容的提问来源于stack exchange,提问作者LeoPkm2-1
相关产品推荐
相关产品推荐

