You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()

[]

请问此处出现了什么问题,该如何修复?


问题原因

  1. $where函数的执行环境差异:
    在Node.js的mongodb驱动中,传递给$where的函数会被序列化为字符串发送到MongoDB服务器执行。虽然代码和mongosh中一致,但服务器端执行new Date()生成的时间可能和客户端本地时间存在差异,或者this.exp在服务器JS环境中的类型转换出现异常,导致对比逻辑反向。
  2. $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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 10:01:12