Mongoose调用findById时报BSONTypeError/ObjectId转换失败问题求助
问题原因
- 核心错误触发逻辑:MongoDB的
ObjectId类型要求传入的值必须是12字节的字符串或者24位十六进制字符,你调用Blog.findById()时传入的id是字符串blogs,不符合格式要求,因此抛出类型转换错误。 - 参数异常来源:这是Express路由匹配顺序错误导致的。Express会按照路由定义的先后顺序从上到下匹配请求路径,你将带动态参数的路由(比如
/:id或者/blogs/:id)定义在了静态路径路由(比如/blogs/create或者/blogs)的前面,当你访问新建博客对应的路径时,请求会先匹配到动态参数路由,把路径里的blogs片段当成了id参数的值传入你的查询逻辑。
解决方法
- 调整路由定义顺序:把所有静态路径的路由放在动态参数路由的前面,示例如下:
错误顺序:
// 动态参数路由在前,会优先匹配所有/blogs/xxx的请求,包括/blogs/create app.get('/blogs/:id', blogController.blog_details) app.get('/blogs/create', blogController.blog_create_get)
正确顺序:
// 静态路由放前面 app.get('/blogs/create', blogController.blog_create_get) app.get('/blogs/:id', blogController.blog_details)
- 增加id格式校验(可选但推荐):在查询数据库之前先校验传入的id是否为合法的ObjectId格式,避免非法请求直接打到数据库:
const mongoose = require('mongoose'); const id = req.params.id.trim(); // 先校验id格式 if (!mongoose.Types.ObjectId.isValid(id)) { return res.status(400).send('无效的博客ID'); } Blog.findById(id) .then((result) => { res.render("details", { blog: result, title: "Blog Details" }); }) .catch((err) => { console.log(err); res.status(404).render('404', { title: '博客不存在' }); });
- 排查新建博客的请求路径是否写错:如果是表单提交或者跳转的路径写错,误把新建请求指向了详情路由,也会出现该问题,确认新建博客对应的请求路径和路由定义的静态路径完全一致。
内容的提问来源于stack exchange,提问作者cdeluchi
相关产品推荐
相关产品推荐

