MongoDB日期范围查询带URL参数崩溃问题排查与方案咨询
MongoDB日期范围查询参数携带时程序崩溃问题排查与解决方案
问题描述
在MongoDB中实现基于from和to参数的日期范围查询,无查询参数时功能正常,但携带参数请求URL时程序崩溃。
错误信息
{"stringValue":""{ fromDate: 'Sat Dec 31 2022' }"","kind":"string","value":{"fromDate":"Sat Dec 31 2022"},"path":"date","reason":null,"valueType":"Object","statusCode":400}
原路由代码
router.get("/:_id/logs", (req, res) => { const fromDate = new Date(req.query.from).toDateString(); const toDate = new Date(req.query.to).toDateString(); User.findById(req.params._id) .then((user) => { Exercise.find({ $and: [ { user: req.params._id }, fromDate !== "Invalid Date" ? { date: { $gte: { fromDate } } } : {}, toDate !== "Invalid Date" ? { date: { $lte: { toDate } } } : {}, ], }) .limit(+req.query.limit) .sort({ date: 1 }) .exec() .then((exercises) => res.json({ username: user.username, userId: user._id, count: exercises.length, logs: exercises, }) ) .catch((err) => res.json({ ...err, statusCode: 400 })); }) .catch((err) => res.json({ ...err, statusCode: 400 })); });
问题分析
- 日期类型错误:代码中将日期转为字符串格式(
toDateString()),但MongoDB的日期查询需要Date对象;同时错误地将{ fromDate }作为$gte的值传入,导致MongoDB无法解析这个嵌套对象为合法日期,触发类型错误。 - 查询条件构建不当:在
$and数组中传入空对象{},会干扰MongoDB的查询逻辑;且条件拆分的方式不符合MongoDB查询语法,多个date条件应该合并到同一个对象中,而非分开的条件项。 - 参数处理不严谨:未先判断
req.query.from/to是否存在就直接转换,当参数不存在时new Date(undefined)会生成无效日期,后续的字符串对比逻辑存在隐患。
修复方案
- 仅在参数存在时转换为
Date对象,保留日期的原生类型供MongoDB查询使用 - 动态构建查询条件对象,将多个日期条件合并到同一个
date字段下,避免空对象干扰 - 优化错误处理逻辑,确保参数转换失败时不生成无效查询条件
优化后的代码
router.get("/:_id/logs", (req, res) => { // 初始化查询条件,默认匹配用户ID const query = { user: req.params._id }; const { from, to, limit } = req.query; // 处理from日期参数 if (from) { const fromDate = new Date(from); if (!isNaN(fromDate.getTime())) { query.date = query.date || {}; query.date.$gte = fromDate; } } // 处理to日期参数 if (to) { const toDate = new Date(to); if (!isNaN(toDate.getTime())) { query.date = query.date || {}; query.date.$lte = toDate; } } User.findById(req.params._id) .then((user) => { Exercise.find(query) .limit(limit ? +limit : undefined) .sort({ date: 1 }) .exec() .then((exercises) => res.json({ username: user.username, userId: user._id, count: exercises.length, logs: exercises, }) ) .catch((err) => res.json({ ...err, statusCode: 400 })); }) .catch((err) => res.json({ ...err, statusCode: 400 })); });
内容的提问来源于stack exchange,提问作者Maciej Kuta
相关产品推荐
相关产品推荐

