MongoDB Mongoose查询报错‘Failed to call method’原因分析
排查MongoDB Mongoose查询抛出InternalError的问题
兄弟,这个问题我太熟了,你这查询踩了$where的好几个坑,咱们一步步拆解问题根源,再给你正确的写法:
核心问题:$where的字符串拼接方式完全错误
你用字符串拼接的方式把new Date()塞进$where的表达式里,这里有个致命的环境差异:
new Date()是在Node.js客户端执行的,生成的是Node环境下的日期字符串(比如Wed Oct 11 2023 14:25:30 GMT+0800 (中国标准时间))- 但
$where的表达式是在MongoDB服务器端的JS引擎里执行的,这个引擎不认识Node生成的这种带时区标识的日期字符串,直接把它当成无效代码,导致执行失败,抛出InternalError。
额外隐患:$where本身不适合这种场景
就算你把日期格式改对了,$where也不是个好选择:
- 性能极差:它会强制Mongo对集合里的每个文档执行JS代码,完全没法利用
expired字段上的索引,数据量一大查询会慢到离谱 - 安全风险:如果拼接的内容来自用户输入,很容易触发MongoDB注入攻击
正确的写法:用常规查询操作符替代$where
Mongoose支持直接用$lte(小于等于)操作符来做日期比较,而且会自动把客户端的Date对象转换成Mongo能识别的BSON日期,完全不需要$where:
sampleSchema.find({ expired: { $lte: new Date() } }) .limit(9) .sort({ postedDate: -1 }) .then((docs) => { console.log('found docs ', docs); }) .catch((err) => { console.log('error ', err); })
额外提醒
以后尽量避免使用$where,只有当你遇到完全无法用常规查询操作符实现的复杂逻辑时,再考虑它——而且那时候也不要直接拼接字符串,要通过参数传递的方式(比如结合$expr或者在$where函数里用this访问文档字段)。
内容的提问来源于stack exchange,提问作者Mr.X
相关产品推荐
相关产品推荐

