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

删除Employee时如何更新Game模型的employees数组?

问题原因分析

你的pre('deleteOne')是文档实例级别的中间件,仅当调用Employee文档实例的deleteOne()方法时才会触发。但控制器中存在两个问题:

  1. 先调用findByIdAndDelete(Model静态方法)直接删除了文档,此操作不会触发实例级的deleteOne钩子;
  2. 后续调用的employee.deleteOne()是多余的——此时文档已被findByIdAndDelete删除,该操作无法生效,自然也不会触发钩子更新Game的employees数组。
解决方案

以下两种方案任选其一即可:

方案1:将钩子改为Query级中间件

修改Employee模型的钩子,让它能响应Model静态方法(如findByIdAndDelete、deleteOne)的删除操作:

employeeSchema.pre('deleteOne', { query: true, document: false }, async function(next) {
  try {
    // 从查询对象中获取要删除的员工ID
    const employeeId = this.getQuery()._id;
    await mongoose.model('Game').updateMany(
      { employees: employeeId },
      { $pull: { employees: employeeId } }
    );
    next();
  } catch (error) {
    next(error);
  }
});

同时简化控制器代码,去掉多余的重复删除操作,并修正HTTP状态码(删除成功应返回200而非201):

exports.deleteEmployee = asyncHandler(async (req, res, next) => {
  const employee = await Employee.findByIdAndDelete(req.params.id);

  if (!employee) {
    return next(
      new ErrorResponse(`Employee not found with id of ${req.params.id}`, 404)
    );
  }

  res.status(200).json({
    success: true,
    data: {},
  });
});

方案2:修改控制器使用实例deleteOne()

保持原有的文档实例级钩子不变,修改控制器先查询到实例,再调用实例的deleteOne()触发钩子:

exports.deleteEmployee = asyncHandler(async (req, res, next) => {
  const employee = await Employee.findById(req.params.id);

  if (!employee) {
    return next(
      new ErrorResponse(`Employee not found with id of ${req.params.id}`, 404)
    );
  }

  // 调用实例方法触发钩子
  await employee.deleteOne();

  res.status(200).json({
    success: true,
    data: {},
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 02:52:22