Node.js后端调用PUT/PATCH接口更新数据时数据库版本字段未更新
问题结论
该问题与PUT、PATCH两种HTTP请求方法的特性完全无关,是Mongoose更新方法的默认配置以及代码逻辑问题导致的。
原因说明
Mongoose的版本字段__v默认仅在调用save()方法更新文档时自动递增,你使用的findByIdAndUpdate属于原子更新操作,默认不会触发版本号自动更新,也不会触发Schema的字段校验逻辑。同时你当前的代码默认返回的是更新前的旧文档,而非更新后的最新数据。
修复方案
方案1(推荐,兼容默认版本控制逻辑)
改为先查询文档,修改后调用save()方法触发版本号自动更新:
router.patch('/update/:id', async (req, res) => { const id = req.params.id; try { const category = await Category.findById(id); if (!category) { // 资源不存在应返回404状态码而非400 return res.status(404).send('Category not found'); } // 合并请求体字段到文档实例,可在此处添加字段过滤逻辑避免非法参数 Object.assign(category, req.body); // save方法会自动触发__v版本号递增和字段校验 await category.save(); return res.status(200).send(category); } catch (err) { return res.status(400).send(err); } });
方案2(保留findByIdAndUpdate写法)
显式配置版本号递增逻辑,同时开启返回新文档、触发校验的参数:
router.patch('/update/:id', async (req, res) => { const id = req.params.id; try { const category = await Category.findByIdAndUpdate( id, { ...req.body, $inc: { __v: 1 } // 手动递增版本号 }, { new: true, // 返回更新后的新文档 runValidators: true // 触发Schema字段校验 } ); if (!category) { return res.status(404).send('Category not found'); } return res.status(200).send(category); } catch (err) { return res.status(400).send(err); } });
如果你的业务场景需要处理并发修改冲突,还可以在查询条件中添加当前请求携带的版本号匹配规则,避免旧版本数据覆盖新版本数据。
内容的提问来源于stack exchange,提问作者KingDark
相关产品推荐
相关产品推荐

