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

Mongoose中findByIdAndUpdate时好时坏,更新文档报_id未定义错误

问题分析与解决

出现TypeError: Cannot read property '_id' of undefined的核心原因有几个:

1. findByIdAndUpdate默认返回旧文档,且未做存在性校验

Opdrachten.findByIdAndUpdate()默认返回更新前的原始文档,如果遇到以下情况就会触发错误:

  • 原始文档的installateurs数组为空
  • 找不到对应_id的Opdracht文档(此时result为null)

而且你没给外层Promise加错误捕获,导致出现UnhandledPromiseRejectionWarning。

2. 嵌套Promise的错误处理缺失

代码里只有最内层的findByIdAndUpdate加了catch,外层的Opdrachten.findByIdAndUpdate和Installateurs.findById都没有错误捕获,任何一步出错都会导致未处理的Promise拒绝。

3. 更新Installateurs的方式不合理

直接把整个res文档传给findByIdAndUpdate会覆盖文档里的其他字段(比如更新时间、其他关联字段),完全没必要,应该只更新需要修改的字段。


修复后的代码(用async/await简化,完善错误处理)

const Installateurs = require("../../Models/Installateurs.js");
const Opdrachten = require("../../Models/Opdracht.js");

const verzendOpdrachtNaarInstallateur = async (req, response) => {
  try {
    // 更新Opdracht,指定{new: true}返回更新后的文档,同时校验文档是否存在
    const updatedOpdracht = await Opdrachten.findByIdAndUpdate(
      req.body._id,
      req.body,
      { new: true }
    );

    if (!updatedOpdracht) {
      return response.status(404).json({ message: "Opdracht不存在" });
    }

    // 校验installateurs数组是否有元素
    if (!updatedOpdracht.installateurs || updatedOpdracht.installateurs.length === 0) {
      return response.status(400).json({ message: "installateurs数组为空,无法获取目标ID" });
    }

    const installateurId = updatedOpdracht.installateurs[0]._id;

    // 用$push只修改目标字段,避免覆盖其他数据
    const updatedInstal = await Installateurs.findByIdAndUpdate(
      installateurId,
      {
        $push: {
          opdrachten: updatedOpdracht._id,
          huidigeOpdracht: updatedOpdracht._id
        }
      },
      { new: true }
    );

    if (!updatedInstal) {
      return response.status(404).json({ message: "Installateur不存在" });
    }

    response.json(updatedInstal);
  } catch (err) {
    console.error("操作出错:", err);
    response.status(500).json({ message: "服务器内部错误", error: err.message });
  }
};

module.exports = verzendOpdrachtNaarInstallateur;

额外注意点

  • 如果你确实需要使用更新前的Opdracht文档,去掉{new: true},但必须确保原始文档的installateurs数组有至少一个元素,否则还是会报错。
  • 尽量用async/await替代嵌套Promise,代码更易读,错误处理更集中。
  • 数据库操作前一定要做存在性校验,避免访问undefined的属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 06:10:32