Mongoose:为找不到文档定义404状态是行不通的



我正在学习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

最新更新