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

Sequelize多对多关联报错:TypeError: Members.belongsToMany不是函数

问题:Sequelize多对多关联报错 TypeError: Members.belongsToMany is not a function

MySQL数据库存在members和events两张表,二者为多对多关系,尝试通过包含member_id、event_id及event_date的中间表member_events使用Sequelize建模,启动Node.js服务器时出现如下错误:

Members.belongsToMany(models.Events, { through: 'member_events' })
        ^
TypeError: Members.belongsToMany is not a function

涉及的三个模型代码如下:

memberEvents.js

module.exports = (sequelize, DataTypes) => {
  const Members = require('../models/members')
  const Events = require('../models/events')
  
  const MemberEvents = sequelize.define(
    "MemberEvents",
    {
      member_id: {
        type: DataTypes.INTEGER,
        allowNull: false,
        primaryKey: true,
      },

      event_id: {
        type: DataTypes.INTEGER,
        allowNull: false,
        primaryKey: true,
      },

      event_date: {
        type: DataTypes.DATEONLY,
        allowNull: false,
        primaryKey: true,
      },
    },
    { tableName: "member_events" }
  );

        Members.belongsToMany(Events, { through: 'member_events' })
        Events.belongsToMany(Members, { through: 'member_events' })


  return MemberEvents;
};

Members.js

module.exports = (sequelize, DataTypes) => {
  //Below creates the member table in the schema
  const Members = sequelize.define(
    "Members",
    {
      member_id: {
        type: DataTypes.INTEGER,
        autoIncrement: true,
        allowNull: false,
        primaryKey: true,
      },

      forename: {
        type: DataTypes.STRING(35),
        allowNull: false,
      },

      surname: {
        type: DataTypes.STRING(35),
        allowNull: false,
      },

      date_of_birth: {
        type: DataTypes.DATEONLY,
        allowNull: false,
      },

      address_1: {
        type: DataTypes.STRING(35),
        allowNull: false,
      },

      address_2: {
        type: DataTypes.STRING(35),
      },

      address_3: {
        type: DataTypes.STRING(35),
      },

      address_4: {
        type: DataTypes.STRING(35),
      },

      address_5: {
        type: DataTypes.STRING(35),
      },

      postcode: {
        type: DataTypes.STRING(12),
        allowNull: false,
      },

      directions: {
        type: DataTypes.TEXT("long"),
      },

      mobile_phone: {
        type: DataTypes.STRING(12),
      },

      email_address: {
        type: DataTypes.STRING(255),
      },

      key_safe_code: {
        type: DataTypes.STRING(8),
      },

      next_of_kin_name: {
        type: DataTypes.STRING(70),
      },

      next_of_kin_phone: {
        type: DataTypes.STRING(12),
      },

      next_of_kin_local: {
        type: DataTypes.STRING(33),
      },

      next_of_kin_relationship: {
        type: DataTypes.STRING(40),
      },

      doctor_name: {
        type: DataTypes.STRING(35),
      },

      initial_medical_conditions: {
        type: DataTypes.TEXT("long"),
      },

      deceased: {
        type: DataTypes.DATEONLY,
      },

      normally_escorted: {
        type: DataTypes.STRING(3),
      },

      blue_badge_holder: {
        type: DataTypes.STRING(3),
      },

      medical_equipment: {
        type: DataTypes.STRING,
      },
    },
    { tableName: "Member" }
  );


  return Members;
};

Events.js

module.exports = (sequelize, DataTypes) => {
  //Below creates the event table in the schema
  const Events = sequelize.define(
    "Events",
    {
      event_id: {
        type: DataTypes.INTEGER,
        autoIncrement: true,
        allowNull: false,
        primaryKey: true,
      },

      event_name: {
        type: DataTypes.STRING(70),
        allowNull: false,
      },

      staff_id: {
        type: DataTypes.INTEGER,
        allowNull: false,
      },
    },
    { tableName: "Events" }
  );


  return Events;
};

原因分析

  1. 模型未正确实例化:直接通过require导入模型文件得到的是模型的定义函数,不是经过Sequelize实例化后的模型对象,这类函数没有belongsToMany等关联方法。
  2. 关联定义位置错误:在中间表模型内部直接引入并定义关联,会导致循环依赖或模型未完成实例化的问题,触发方法不存在的错误。

解决方法

步骤1:修改中间表模型,移除关联定义

将memberEvents.js中的require语句和关联代码删除,只保留中间表的模型定义:

module.exports = (sequelize, DataTypes) => {
  const MemberEvents = sequelize.define(
    "MemberEvents",
    {
      member_id: {
        type: DataTypes.INTEGER,
        allowNull: false,
        primaryKey: true,
      },

      event_id: {
        type: DataTypes.INTEGER,
        allowNull: false,
        primaryKey: true,
      },

      event_date: {
        type: DataTypes.DATEONLY,
        allowNull: false,
        primaryKey: true,
      },
    },
    { tableName: "member_events" }
  );

  return MemberEvents;
};

步骤2:统一在外部定义关联

创建一个专门的关联初始化文件(如associations.js),在所有模型都被Sequelize加载完成后,通过Sequelize的models对象访问实例化后的模型来定义关联:

// 接收已加载所有模型的models对象
module.exports = (models) => {
  const { Members, Events, MemberEvents } = models;

  // 定义多对多关联,明确指定中间表模型及外键
  Members.belongsToMany(Events, { 
    through: MemberEvents, 
    foreignKey: 'member_id',
    otherKey: 'event_id'
  });
  Events.belongsToMany(Members, { 
    through: MemberEvents, 
    foreignKey: 'event_id',
    otherKey: 'member_id'
  });
};

步骤3:在初始化流程中调用关联设置

在你的数据库初始化文件或服务器入口文件中,先加载所有模型,再调用关联初始化函数:

const sequelize = require('./path-to-your-sequelize-instance');
// 假设models目录下的index.js已导出所有实例化后的模型
const models = require('./models');

// 初始化模型关联
require('./associations')(models);

// 后续启动服务器或执行数据库同步操作

注意事项

  • 确保所有模型都通过Sequelize实例正确加载,models对象中的每个模型都是经过sequelize.define实例化后的对象,才会拥有关联方法。
  • 关联中指定的foreignKey和otherKey要与中间表的字段名完全对应,避免Sequelize自动生成错误的字段。
  • 不要在单个模型文件内部直接导入其他模型定义关联,避免循环依赖和实例化不完整的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 11:05:19