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

Mongoose 6.0.12下带必填字段模型的findOneAndUpdate报错如何解决

定位方法

首先在catch块中打印完整错误信息,查看err.message与err.errors字段,即可快速判断错误类型:

  • 如果是语法类报错,基本是await与回调混用导致
  • 如果是字段校验类报错,会明确标注哪个必填字段缺失
问题核心原因
  1. await与回调函数混用冲突
    Mongoose 6.x版本开始不再支持同时使用await(Promise调用方式)和回调函数两种异步写法,你当前代码同时传入了回调参数又使用await修饰,会直接触发执行报错。
  2. upsert场景必填字段校验触发
    你开启了upsert: true配置,如果执行更新时对应userId的用户不存在,会触发新建用户逻辑,此时你只传入了picture字段,pseudo、email、password等必填字段都未提供,Mongoose 6.x默认会校验所有schema规则,就会抛出校验失败错误。
解决方案
  • 第一步:统一异步写法,移除回调函数,全部使用async/await+try/catch处理逻辑,修正后的代码如下:
try {
    const docs = await UserModel.findByIdAndUpdate(
      req.body.userId,
      { $set : {picture: "./uploads/profile/" + fileName}},
      { new: true, upsert: true, setDefaultsOnInsert: true}
    );
    return res.send(docs);
  } catch (err) {
    // 此处打印err可查看完整错误信息
    console.log(err);
    return res.status(500).send({ message: err });
  }
  • 第二步:根据业务场景处理校验逻辑
    • 如果你确认当前操作仅更新已存在的用户,不会触发新建逻辑,可以把upsert: true改为upsert: false,避免触发必填字段校验
    • 如果你确实需要支持upsert新建逻辑,可以使用$setOnInsert操作符补充所有必填字段的插入默认值,示例如下:
    const docs = await UserModel.findByIdAndUpdate(
      req.body.userId,
      { 
        $set : {picture: "./uploads/profile/" + fileName},
        // 只有触发upsert新建时才会执行该字段赋值
        $setOnInsert: {
          pseudo: '新建用户默认用户名',
          email: '新建用户默认邮箱',
          password: '加密后的默认密码'
        }
      },
      { new: true, upsert: true, setDefaultsOnInsert: true}
    );
    
    • 如果你不需要校验更新/插入时的字段规则,可以临时关闭校验(不推荐,会跳过所有schema规则校验,容易产生脏数据),配置参数如下:
    { 
      new: true, 
      upsert: true, 
      setDefaultsOnInsert: true,
      runValidators: false
    }
    

内容的提问来源于stack exchange,提问作者ilyes amen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 12:45:03