我正在学习MongoDB和mongoose,现在我在为路由处理程序定义404状态时遇到了问题。这是代码:
app.get('/users/:id', async (req, res) => {
const _id = req.params.id
try {
const user = await User.findById(_id)
if (!user) {
return res.status(404).send()
}
res.send(user)
} catch (error) {
res.status(500).send()
}
})
现在,如果我给它一个不存在的id,它不会给我404未找到的状态。它只执行catch块,这不是我想要的。如果你能告诉我在哪里犯了错误,或者告诉我一种处理错误的方法,我将不胜感激。感谢
问题
如您在日志中所见
CastError: Cast to ObjectId failed for value "6082d50a2c89db3164" at path "_id" for model "User"
这意味着:您提供给findById
函数的值("6082d50a2c89db3164"(不是有效的ObjectId。然后执行catch块。
建议
1.在数据库中查询前验证参数
我知道您试图提供一些数据库中不存在的id进行测试。但是IMHO,两种情况之间存在差异:
- 您提供了一个有效的id,但在数据库中找不到该id。在这种情况下,它应该返回404
- 如果您在请求中提供了一个无效的id,它可能是一个类似"的字符串;6082d50a2c89db3164";,或者甚至"#Q*&(#@*"或我们能想象到的任何东西。对于这种情况,如果我们验证输入(req.params._id(以确保格式有效,可能会更好。代码如下所示:
app.get('/users/:id', async (req, res) => {
const _id = req.params.id;
// validate params
if(!isValidateObjectId(_id)) { // the function we need to write
res.status(200).send("Invalid params"); // you can define your status and message
return;
}
// good params, get user from database
try {
const user = await User.findById(_id)
if (!user) {
return res.status(404).send()
}
res.send(user)
} catch (error) {
res.status(500).send()
}
})
2.使用findOne((方法而不是findById
如果您想要一个更简单的解决方案,请不要使用findById,因为函数需要一个有效的ObjectId。我们可以使用findOne((方法:
app.get('/users/:id', async (req, res) => {
const _id = req.params.id
try {
const user = await User.findOne({_id : _id})
if (!user) {
return res.status(404).send()
}
res.send(user)
} catch (error) {
res.status(500).send()
}
})
(IMHO,第一个解决方案更好。(
一些有用的链接:
- https://docs.mongodb.com/manual/reference/method/ObjectId/
- 我可以确定字符串是否是MongoDB ObjectID吗
- https://mongoosejs.com/docs/api.html#model_Model.findOne