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

如何通过连接表查询Sequelize模型?使用through:model时报错

Sequelize多对多关联查询报错:TypeError: Cannot read properties of undefined (reading 'getTableName')

问题背景

开发练习用Web应用,单模型查询数据库正常,但通过连接表实现多对多关联查询时出错,需求是获取指定用户加入的所有聊天会话。

执行的查询代码

const models = require('../db/models');

// 在API接口内
const userChats = await models.User.findOne({ 
    where: { id: req.user.id },
    include: [
        {
            model: models.Chat,
            through: models.User_Chat
        }
    ]
});

报错信息

C:\...mypath...\node_modules\sequelize\lib\dialects\abstract\query-generator.js:1376
    const throughTable = through.model.getTableName();
                                       ^

TypeError: Cannot read properties of undefined (reading 'getTableName')

相关模型定义

Chat模型

const { sq } = require("../config/db");
const { DataTypes } = require('sequelize');

const Chat = sq.define('Chat', {
    id: {
        type: DataTypes.UUID,
        primaryKey: true,
        defaultValue: DataTypes.UUIDV4,
        allowNull: false
    },
    name: {
        type: DataTypes.STRING,
        allowNull: false
    }
}, {
    tableName: 'chats',
    timestamps: true,
});

Chat.associate = (models) => {
    Chat.belongsToMany(models.User, { through: models.User_Chat, foreignKey: 'chat_id', otherKey: 'user_id' });
    Chat.hasMany(models.Message, { foreignKey: 'chat_id'});
    Chat.belongsTo(models.User, { foreignKey: 'creator_id'});
};

module.exports = { Chat };

User模型

const { sq } = require("../config/db");
const { DataTypes, Sequelize } = require('sequelize');

const User = sq.define("User", {
    id: {
        type: DataTypes.UUID,
        defaultValue: DataTypes.UUIDV4,
        primaryKey: true,
        allowNull: false,
    },
    email: {
        type: DataTypes.STRING,
        allowNull: false,
        validate: {
            is: /^[\w-]+(?:\.[\w-]+)*@(?:[\w-]+\.)+[a-zA-Z]{2,7}$/
        },
        unique: true
    },
    password: {
        type: DataTypes.STRING,
        allowNull: false,
    },
}, {
    tableName: 'users'
});

User.associate = (models) => {
    User.belongsToMany(models.Chat, { through: models.User_Chat, foreignKey: 'user_id', otherKey: 'chat_id' });
    User.hasMany(models.Message, { foreignKey: 'sender_id' });
    User.hasMany(models.Chat, { foreignKey: 'creator_id' });
};

module.exports = { User }

User_Chat连接表模型

const { sq } = require("../../config/db"); 
const { DataTypes, Sequelize } = require('sequelize');

const User_Chat = sq.define('User_Chat', {
    user_id: {
        type: DataTypes.UUID,
        allowNull: false
    },
    chat_id: {
        type: DataTypes.UUID,
        allowNull: false
    }
}, {
    tableName: 'users_chats'
});

module.exports = { User_Chat }

模型初始化代码

// Imported models
const UserModel = require('./user').User;
const ChatModel = require('./chat').Chat;
const MessageModel = require('./message').Message;

// Imported junction model(s)
const User_ChatModel = require('./junctions/user_chat').User_Chat;

// Initialize models
const models = {
  User: UserModel,
  Chat: ChatModel,
  Message: MessageModel,
  User_Chat: User_ChatModel
};
console.log('\n model index running \n');
// Apply associations
Object.keys(models).forEach(modelName => {
    console.log('\nmodel name:', modelName, 'associating');
    if (models[modelName].associate) {
    models[modelName].associate(models);
  }
});

module.exports = models;

问题分析与解决方案

核心错误原因

在include配置中手动指定through: models.User_Chat是多余且不符合语法要求的。你已经在User.belongsToMany(models.Chat)和Chat.belongsToMany(models.User)的关联定义中指定了连接表,Sequelize会自动复用这个配置。手动传入模型对象作为through值,会导致Sequelize内部无法正确解析连接表元数据,从而抛出cannot read getTableName错误。

修复步骤

  1. 简化查询代码:去掉include中的through配置,直接关联models.Chat即可:
const userChats = await models.User.findOne({ 
    where: { id: req.user.id },
    include: [models.Chat]
});
  1. 规范连接表定义(可选但推荐):为连接表的复合字段添加主键标识,让Sequelize更清晰识别关联关系:
const User_Chat = sq.define('User_Chat', {
    user_id: {
        type: DataTypes.UUID,
        allowNull: false,
        primaryKey: true // 标记为主键
    },
    chat_id: {
        type: DataTypes.UUID,
        allowNull: false,
        primaryKey: true // 标记为主键
    }
}, {
    tableName: 'users_chats',
    timestamps: false // 不需要 createdAt/updatedAt 可关闭,避免冗余字段
});
  1. 验证关联初始化:当前模型初始化代码已正确遍历执行所有associate方法,确保关联关系加载正常,无需修改。

预期结果

修复后,Sequelize会自动通过users_chats表关联users.id与users_chats.user_id、chats.id与users_chats.chat_id,返回包含该用户及所属所有聊天会话的完整数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 13:37:08