Sequelize报错:Question未与Survey关联,请求排查解决
解决Sequelize报错“Question is not associated to Survey”
问题背景
作为Node.js初学者,使用PostgreSQL数据库完成登录、注册API后,开发进阶功能时遇到Sequelize报错:Question is not associated to Survey,尝试多种方案仍未解决。相关代码如下:
Survey 模型
module.exports = function(sequelize, DataTypes) { const Survey = sequelize.define("Survey", { survey_id: { autoIncrement: true, type: DataTypes.INTEGER.UNSIGNED, allowNull: false, primaryKey: true, }, required: { type: DataTypes.INTEGER }, title: { type: DataTypes.STRING }, description: { type: DataTypes.STRING }, status: { type: DataTypes.INTEGER }, endDate: { type: DataTypes.DATE }, userid: { type: DataTypes.INTEGER } },{ tableName: 'survey', hooks, }); Survey.sync({ alter: true }) Survey.associate = function(models) { Survey.belongsTo(models.User, {foreignKey: 'userid'}); Survey.hasMany(models.Question); }; return Survey }
Question 模型
module.exports = function (sequelize, DataTypes) { const Question = sequelize.define("Question", { question_id: { autoIncrement: true, type: DataTypes.INTEGER.UNSIGNED, allowNull: false, primaryKey: true, }, question_type: { type: DataTypes.INTEGER }, question_title: { type: DataTypes.STRING }, question_required: { type: DataTypes.INTEGER }, survey_id: { type: DataTypes.INTEGER } }, { tableName: 'question', hooks, }); Question.sync({alter: true}) Question.associate = (models) => { Question.belongsTo(models.Survey, {foreignKey: 'survey_id'}); // Question.hasMany(models.QuestionOption, {foreignKey: 'question_id'}); }; return Question }
控制器代码
Survey.findAll({ where: { userid: userId }, include: { model: Question, } }).then(data => { res.status(200).send(formatResponse(false, 'Survey list', data)); }).catch(error => { res.status(500).send(formatResponse(true, error.message || "Error in Fetching Data", {})); })
问题排查与解决方案
1. 显式指定关联外键
Sequelize自动推断外键时默认使用模型名+Id格式(如SurveyId),但你的Question表中用的是survey_id,需在Survey的hasMany关联中显式指定外键:
修改Survey模型的associate方法:
Survey.associate = function(models) { Survey.belongsTo(models.User, {foreignKey: 'userid'}); // 显式指定外键为survey_id Survey.hasMany(models.Question, { foreignKey: 'survey_id' }); };
2. 确保模型关联被正确初始化
检查项目是否有统一加载模型的入口文件(通常为models/index.js),该文件需遍历所有模型并调用associate方法。若没有,创建或修改该文件:
const fs = require('fs'); const path = require('path'); const Sequelize = require('sequelize'); const basename = path.basename(__filename); const env = process.env.NODE_ENV || 'development'; const config = require(__dirname + '/../config/config.json')[env]; const db = {}; let sequelize; if (config.use_env_variable) { sequelize = new Sequelize(process.env[config.use_env_variable], config); } else { sequelize = new Sequelize(config.database, config.username, config.password, config); } // 加载所有模型 fs .readdirSync(__dirname) .filter(file => { return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); }) .forEach(file => { const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes); db[model.name] = model; }); // 调用所有模型的associate方法 Object.keys(db).forEach(modelName => { if (db[modelName].associate) { db[modelName].associate(db); } }); db.sequelize = sequelize; db.Sequelize = Sequelize; module.exports = db;
3. 统一数据库同步时机
去掉每个模型中的sync调用,改为在项目启动时统一执行同步,避免模型初始化顺序问题:
在启动文件(如app.js或server.js)中:
const express = require('express'); const app = express(); const db = require('./models'); const port = process.env.PORT || 3000; // 其他中间件配置... // 同步数据库并启动服务 db.sequelize.sync({ alter: true }).then(() => { console.log('数据库同步完成'); app.listen(port, () => { console.log(`服务运行在端口 ${port}`); }); }).catch(err => { console.error('数据库同步失败:', err); });
4. 控制器中正确引用模型
确保控制器从统一的models对象导入Survey和Question,而非直接导入单个模型文件:
const { Survey, Question } = require('../models'); // 后续查询代码保持不变 Survey.findAll({ where: { userid: userId }, include: { model: Question, } }) // ...
验证
完成以上修改后,重启服务并测试查询接口,报错应会消失,Survey数据将正确关联并返回对应的Question列表。
内容的提问来源于stack exchange,提问作者Avinash
相关产品推荐
相关产品推荐

