Mongoose findByIdAndUpdate返回正常但MongoDB数据未更新
问题原因
你代码里有4个直接导致数据无法写入MongoDB的错误:
- 路由用了
GET方法:常规HTTP服务的Body解析中间件默认不会处理GET请求的请求体,你代码里取的req.body.username实际是undefined;且好友添加属于数据写操作,本身就应该用POST/PUT类写请求方法,不能用GET。 - 路由处理函数定义错误:你写的处理函数既没有加
async关键字,也没有接收req、res形参。函数内的await在非async函数里无法生效,直接调用req/res会触发引用错误,整个更新逻辑根本没有正常执行到数据库写入步骤。 findByIdAndUpdate缺少必填配置:这个Mongoose方法默认返回更新前的原始文档,且当查询条件传入的是从中间件查出来的Mongoose文档实例时,部分版本下只会修改内存中的文档对象,不会实际向MongoDB发送写入命令——这就是你控制台打印u能看到新好友数据,但数据库里没变化的核心原因,你看到的是内存里临时修改的对象,不是数据库持久化后的结果。- 鉴权中间件没有错误捕获:
jwt.verify遇到过期、伪造的token会直接抛出异常,没有捕获的话会直接中断请求,根本走不到后续更新逻辑。
修复方案
- 把路由请求方法从
GET改为POST,给路由处理函数加上async标记,补全req、res形参 - 给
findByIdAndUpdate传入第三个配置参数,指定返回更新后的文档、写入时执行Schema校验 - 给鉴权中间件加上异常捕获,提前拦截无效token
- 确认Express服务在路由注册前已经挂载了JSON请求体解析中间件
修复后的路由代码
// 注意请求方法改为POST,处理函数加async,补全req、res参数 app.post("/add", userController.auth, async (req, res) => { try { const updatedUser = await users.findByIdAndUpdate( req.user._id, { $push: { friends: { name: req.body.username } } }, // 核心配置,缺一不可 { new: true, // 返回更新完成后的新文档,而非更新前的旧文档 runValidators: true // 写入时强制执行Schema定义的校验规则 } ) console.log(updatedUser); return res.status(201).json({ friends: updatedUser.friends }) } catch (err) { return res.status(500).json({ msg: "好友添加失败", error: err.message }) } })
修复后的鉴权中间件
exports.auth = async (req, res, next) => { try { const token = req.headers["token"]; if (!token) return res.status(401).json({ msg: "请先登录" }) const verifyToken = jwt.verify(token, "i_put_my_secret_here") const currentUser = await users.findOne({ _id: verifyToken.id }).select("-password") if (!currentUser) return res.status(401).json({ msg: "用户身份无效" }) req.user = currentUser next() } catch (err) { return res.status(401).json({ msg: "鉴权失败,请重新登录", error: err.message }) } }
前置配置检查
确认你的Express入口文件中,在所有路由注册之前已经挂载了内置的JSON解析中间件,否则req.body会一直是undefined:
const express = require('express') const app = express() // 必须在路由注册前挂载 app.use(express.json()) // 后续再写app.use('/xxx', xxxRouter)这类路由注册代码
内容的提问来源于stack exchange,提问作者Elad87
相关产品推荐
相关产品推荐

