You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 14:57:04