Express中同API接口POST可用但GET报CastError的原因
图书搜索API GET请求报错原因分析
开发图书搜索API接口时,使用POST方法(无请求体)能正常实现预期功能,但改用GET方法调用时出现如下错误:
CastError: Cast to ObjectId failed for value "search" (type string) at path "_id" for model "bookmodel" at model.Query.exec (E:\FullStacks\BookStore\node_modules\mongoose\lib\query.js:4803:21) at model.Query.Query.then (E:\FullStacks\BookStore\node_modules\mongoose\lib\query.js:4902:15) at processTicksAndRejections (node:internal/process/task_queues:96:5) { messageFormat: undefined, stringValue: '"search"', kind: 'ObjectId', value: 'search', path: '_id', reason: BSONTypeError: Argument passed in must be a string of 12 bytes or a string of 24 hex characters or an integer }
相关配置代码如下:
路由配置
router.get("/search", bookcontoller.searchBook)
控制器方法
async searchBook(req, res) { try { const { query } = req.query; console.log(query); if (!query) { return res.status(400).json({ success: false, msg: "query not found" }); } const searchResult = await bookModel.find({$or:[{name:{$regex:".*"+query+".*"}}, {genre:{$regex:".*"+query+".*"}}]}) if(searchResult.length == 0){ return res.json({success:false, msg:"nothing found of that query"}) } return res.status(200).json({success:true, msg:"search has been successful", searchResult}) } catch (error) { return res.status(400).json(error); } }
请求URL
localhost:8000/book/search?query=hi
报错原因
核心问题是路由顺序冲突:你项目中必然存在一个根据_id查询单本图书的路由(比如router.get("/:id", bookcontroller.getBookById)),并且这个路由的定义顺序在/search路由之前。
Express的路由匹配是按顺序执行的,当请求/book/search时,会先匹配到/:id路由,把字符串search当作id参数传入。Mongoose接收到这个参数后,会尝试将其转换为MongoDB的ObjectId类型,但search不符合ObjectId的格式要求(12字节字符串、24位十六进制字符串或整数),因此抛出CastError。
POST方法能正常工作是因为POST的路由规则和GET的/:id路由不冲突,不会被错误匹配。
解决方案
将/search路由的定义移到/:id路由的前面,确保Express优先匹配搜索路由,避免把search解析成id参数:
// 先定义搜索路由 router.get("/search", bookcontoller.searchBook); // 再定义根据id查询的路由 router.get("/:id", bookcontroller.getBookById);
内容的提问来源于stack exchange,提问作者Dhiran Sapkota
相关产品推荐
相关产品推荐

