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

使用Mongoose遇Customer.findByIdAndUpdate is not a function错误求助

解决Customer.findByIdAndUpdate is not a function错误

问题背景

使用MongoDB、Mongoose和Express开发客户数据库管理系统,主营二手复印机/打印机转售及维护合约业务,客户与机器为关联文档。删除机器时触发以下错误:

Customer.findByIdAndUpdate is not a function
TypeError: Customer.findByIdAndUpdate is not a function at module.exports.deleteMachine (C:\controllers\machines.js:21:20) at C:\utils\catchAsync.js:3:9 at Layer.handle [as handle_request] (C:\node_modules\express\lib\router\layer.js:95:5) at next (C:\node_modules\express\lib\router\route.js:144:13) at module.exports.getCustomer (C:\middleware.js:15:5) at processTicksAndRejections (node:internal/process/task_queues:96:5)

相关代码如下:

机器控制器

const Customer = require('../models/customer');
const Machine = require('../models/machine');

module.exports.deleteMachine = async (req, res) => {
  const { id, machineId } = req.params;
  await Customer.findByIdAndUpdate(id, { $pull: { machines: machineId } });
  await Machine.findByIdAndDelete(machineId);
  req.flash('success', 'Machine has been deleted');
  res.redirect(`/customers/${id}`);
};

机器路由

router.delete('/:machineId', getCustomer, catchAsync(machines.deleteMachine));

getCustomer中间件

module.exports.getCustomer = async (req, res, next) => {
  const { id } = req.params;
  const customer = await Customer.findById(id).populate({ path: 'machines' });
  if (!customer) {
      req.flash('error', 'Sorry, that customer cannot be found!');
      return res.redirect('/customers');
  }
  res.locals.foundCustomer = customer;
  next();
};

app.js路由配置

const customerRoutes = require('./routes/customers');
const machineRoutes = require('./routes/machines');
app.use('/customers', customerRoutes);
app.use('/customers/:id/machines', machineRoutes);

客户模型

const customerSchema = new Schema({
  customer: String,
  customerID: String,
  category: {
      type: String,
      enum: ['contracted', 'billable']
  },
  contacts: [contactSchema],
  address: String,
  city: String,
  state: String,
  zip: String,
  county: String,
  machines: [
      {
          type: Schema.Types.ObjectId,
          ref: 'Machine'
      }
  ],
  notes: [noteSchema]
});

问题原因

错误核心是Customer模型未正确导出为Mongoose模型对象。你提供的客户模型仅定义了Schema,但缺少mongoose.model()的导出语句,导致require('../models/customer')获取的不是具备静态方法的模型实例,自然无法调用findByIdAndUpdate。

解决方案

  1. 补全客户模型的导出代码
    在客户模型文件末尾添加以下代码:

    const mongoose = require('mongoose');
    // (已有的Schema定义)
    module.exports = mongoose.model('Customer', customerSchema);
    

    确保文件顶部已引入mongoose和Schema:

    const mongoose = require('mongoose');
    const Schema = mongoose.Schema;
    
  2. 验证模型导出与路径正确性
    检查控制器中const Customer = require('../models/customer')的路径是否指向正确的模型文件,确认文件确实导出了Mongoose模型而非仅Schema。

  3. 优化代码(可选)
    利用中间件中已查询到的res.locals.foundCustomer进行更新,减少重复查询:

    // 在deleteMachine控制器中替换原更新语句
    await res.locals.foundCustomer.updateOne({ $pull: { machines: machineId } });
    

    同时建议使用Mongoose事务保证操作原子性,避免数据不一致:

    const session = await mongoose.startSession();
    session.startTransaction();
    try {
      await res.locals.foundCustomer.updateOne({ $pull: { machines: machineId } }, { session });
      await Machine.findByIdAndDelete(machineId, { session });
      await session.commitTransaction();
      req.flash('success', 'Machine has been deleted');
      res.redirect(`/customers/${id}`);
    } catch (err) {
      await session.abortTransaction();
      req.flash('error', 'Failed to delete machine');
      res.redirect(`/customers/${id}`);
    } finally {
      session.endSession();
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 23:09:21