Node.js+Mongoose查询Post时报Cast to ObjectId失败错误如何解决
错误触发原因
你贴出的根路径路由代码和Post模型本身不存在问题,该报错的根本原因是路由匹配顺序错误+动态参数路由的非法_id查询,具体逻辑如下:
- Express的路由匹配按照代码编写的先后顺序执行,匹配到第一个符合规则的路由后就会终止后续匹配
- 你项目中一定存在另一个带动态
_id参数的路由,且这个路由的编写顺序在同路径下的静态路由之前,典型的错误写法参考:// 错误:动态参数路由写在静态路由前 app.get('/posts/:id', (req, res) => { // 该路由内调用了Post.findById(req.params.id)查询单篇帖子 Post.findById(req.params.id).lean() .then(post => res.render('post-detail', { post })) .catch(err => console.log(err.message)) }) // 静态路由写在动态路由之后,永远不会被匹配到 app.get('/posts/new', (req, res) => { res.render('post-create') }) - 当你访问
/posts/new路径时,Express会优先匹配到前面的/posts/:id路由,把字符串new赋值给req.params.id传入findById方法 - Mongoose的
findById方法默认会把传入的参数转换为ObjectId类型,而new不符合24位十六进制的ObjectId格式,就会抛出你遇到的报错。
修复方案
- 调整路由编写顺序:所有静态路由放在同路径的动态参数路由前面,保证静态路径优先被匹配:
// 先写静态路由 app.get('/posts/new', (req, res) => { res.render('post-create') }) // 再写动态参数路由 app.get('/posts/:id', (req, res) => { Post.findById(req.params.id).lean() .then(post => res.render('post-detail', { post })) .catch(err => console.log(err.message)) }) - 可选优化:给动态参数路由添加格式校验,仅当参数符合ObjectId规则时才匹配该路由,避免非法参数进入查询逻辑:
// 仅id为24位十六进制字符时才匹配该路由 app.get('/posts/:id([a-fA-F0-9]{24})', (req, res) => { Post.findById(req.params.id).lean() .then(post => res.render('post-detail', { post })) .catch(err => console.log(err.message)) })
内容的提问来源于stack exchange,提问作者bulbapoor
相关产品推荐
相关产品推荐

