Node.js中MongoDB的.updateOne无法更新用户api_token问题
问题分析与解决方案
问题原因
- 更新条件不匹配:
updateOne使用req.body._id作为匹配条件,但登录请求的请求体中并未传入_id字段,导致MongoDB无法找到对应文档(从控制台输出的matchedCount: 0可确认),因此没有文档被更新。 - 异步流程未同步:
updateOne是异步操作,当前代码直接返回了查询到的旧user对象,未等待更新操作完成,即便后续更新成功,返回给客户端的仍是未更新的数据。
解决方案
方式一:修正updateOne条件并等待异步操作完成
app.post('/authenticate', (req, res) => { const { username, password, is_team_driver_login } = req.body const EPK = req.headers['epk'] if(EPK !== process.env.EPK){ return res.status(401).json({message : `Error 401 : Missing or invalid API key`}) } Users.findOne({ username: {$regex: new RegExp(username, 'i') } }).then(async (user) => { if(!user){ console.log('User not found') return res.status(401).json({message : `User ${username} not found`}) } if(user.password !== password) { console.log(`Incorrect Password for user ${username}`) return res.status(401).json({message : `Password incorrect`}) } const token = jwt.sign({username: user.username}, process.env.SECRET_TOKEN) // 使用查询到的user._id作为匹配条件 const updateResult = await Users.updateOne( {"_id": user._id}, { $set : { "api_token": token } }) console.log(updateResult) // 更新本地user对象的api_token后返回,或重新查询最新文档 user.api_token = token console.log(user + '\n' + token) return res.status(200).json(user) }).catch((err) => { console.log(err) res.status(400).json({message : `Bad request`}) }) })
- 用
async/await等待updateOne执行完成,确保更新操作结束后再返回响应。 - 直接修改本地
user对象的api_token字段返回,也可调用Users.findById(user._id)重新拉取最新文档返回。
方式二:使用findOneAndUpdate一步完成查询与更新(更高效)
app.post('/authenticate', (req, res) => { const { username, password, is_team_driver_login } = req.body const EPK = req.headers['epk'] if(EPK !== process.env.EPK){ return res.status(401).json({message : `Error 401 : Missing or invalid API key`}) } Users.findOne({ username: {$regex: new RegExp(username, 'i') } }).then((user) => { if(!user){ console.log('User not found') return res.status(401).json({message : `User ${username} not found`}) } if(user.password !== password) { console.log(`Incorrect Password for user ${username}`) return res.status(401).json({message : `Password incorrect`}) } const token = jwt.sign({username: user.username}, process.env.SECRET_TOKEN) // 匹配用户_id并更新api_token,通过new: true返回更新后的文档 return Users.findOneAndUpdate( {"_id": user._id}, {$set: {"api_token": token}}, {new: true} ) }).then((updatedUser) => { console.log(updatedUser) return res.status(200).json(updatedUser) }).catch((err) => { console.log(err) res.status(400).json({message : `Bad request`}) }) })
findOneAndUpdate将查询和更新合并为一个操作,通过{new: true}直接获取更新后的用户文档,无需额外修改或查询步骤,代码更简洁高效。
内容的提问来源于stack exchange,提问作者Damyon Olson
相关产品推荐
相关产品推荐

