#javascript #node.js #express #sequelize.js
#javascript #node.js #выразить #sequelize.js
Вопрос:
Добрый день! Когда я создаю ассоциации между моделями User и Test, sequelize работает нормально. Но когда я хочу добавить новые ассоциации для теста и вопроса, затем sequelize добавляет новый столбец (мой внешний ключ test_id
и дополнительный testId
).
Почему?
user.js
module.exports = (sequelize, DataType) => {
const User = sequelize.define('user', {
username: {
type: DataType.STRING,
unique: true,
},
password: {
type: DataType.STRING,
},
});
User.associate = (models) => {
User.hasMany(models.test, {
foreignKey: 'id',
});
};
return User;
};
test.js
module.exports = (sequelize, DataType) => {
const Test = sequelize.define('test', {
title: {
type: DataType.STRING,
unique: true,
required: true,
},
description: {
type: DataType.TEXT,
required: true,
},
picture: { // picture link
type: DataType.STRING,
},
});
Test.associate = (models) => {
Test.belongsTo(models.user, {
foreignKey: 'user_id',
});
};
Test.associate = (models) => {
Test.hasMany(models.question, {
foreign_key: 'id',
});
};
return Test;
};
question.js
module.exports = (sequelize, DataType) => {
const Question = sequelize.define('question', {
title: {
type: DataType.STRING,
required: true,
},
});
Question.associate = (models) => {
Question.belongsTo(models.test, {
foreignKey: 'test_id',
});
};
return Question;
};
index.js
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
require('dotenv').config();
const config = process.env;
const basename = path.basename(module.filename);
const sequelize = new Sequelize({
database: config.DB_NAME,
username: config.DB_USER,
password: config.DB_PASS,
dialect: config.DB_DIALECT,
});
const db = {};
fs
.readdirSync(__dirname)
.filter(file => (file.indexOf('.') !== 0) amp;amp; (file !== basename))
.forEach((file) => {
const model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
Object.keys(db).forEach((modelName) => {
if ('loadScopes' in db[modelName]) {
db[modelName].loadScopes(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
Эти модели генерируют некоторые SQL-запросы:
Executing (default): CREATE TABLE IF NOT EXISTS `users` (`id` INTEGER NOT NULL auto_increment , `username` VARCHAR(255) UNIQUE, `password` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
Executing (default): SHOW INDEX FROM `users` FROM `nrforms`
Executing (default): CREATE TABLE IF NOT EXISTS `tests` (`id` INTEGER NOT NULL auto_increment , `title` VARCHAR(255) UNIQUE, `description` TEXT, `picture` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`), FOREIGN KEY (`id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB;
Executing (default): SHOW INDEX FROM `tests` FROM `nrforms`
Executing (default): CREATE TABLE IF NOT EXISTS `questions` (`id` INTEGER NOT NULL auto_increment , `title` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `test_id` INTEGER, `testId` INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`test_id`) REFERENCES `tests` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, FOREIGN KEY (`testId`) REFERENCES `tests` (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB;
Executing (default): SHOW INDEX FROM `questions` FROM `nrforms`
Ответ №1:
Добавьте underscored: false
все свои модели:
module.exports = (sequelize, DataType) => {
const Question = sequelize.define('question', {
title: {
type: DataType.STRING,
required: true,
},
},
{
underscored: false, // <---- add this in all your models
});
Question.associate = (models) => {
Question.belongsTo(models.test, {
foreignKey: 'test_id',
});
};
return Question;
};
Комментарии:
1. Спасибо, но почему ассоциации user и test не создали столбец userId.
2. Это не работает. «СОЗДАТЬ ТАБЛИЦУ, ЕСЛИ ОНА НЕ СУЩЕСТВУЕТ
questions
(id
ЦЕЛОЕ ЧИСЛО НЕ РАВНО НУЛЮ auto_increment ,title
VARCHAR(255),createdAt
ДАТА-ВРЕМЯ НЕ РАВНО НУЛЮ,updatedAt
ДАТА-ВРЕМЯ НЕ РАВНО НУЛЮ,test_id
ЦЕЛОЕ ЧИСЛО,testId
ЦЕЛОЕ ЧИСЛО, ПЕРВИЧНЫЙ КЛЮЧ (id
),test_id
ССЫЛКИ НА ВНЕШНИЙ КЛЮЧtests
(id
) ПРИ УДАЛЕНИИ УСТАНАВЛИВАЮТ ЗНАЧЕНИЕ NULL ПРИ КАСКАДНОМ ОБНОВЛЕНИИ, ССЫЛКИ НА ВНЕШНИЙ КЛЮЧ (testId
)tests
id
УСТАНАВЛИВАЮТ ЗНАЧЕНИЕ NULL ПРИ УДАЛЕНИИNULL ПРИ ОБНОВЛЕНИИ КАСКАДА) ENGINE=InnoDB; Выполнение (по умолчанию): ПОКАЗАТЬ ИНДЕКСquestions
ИЗ `nrforms«3. TestID — был сгенерирован.
4. Это должно было быть решено этим… Мне нужно будет это проверить
Ответ №2:
Я обнаружил проблему.
Test.associate = (models) => {
Test.hasMany(models.question, {
foreignKey: 'id', // was foreign_key: 'id'
});
};
Может быть, это ошибка или триггер для автоматического создания обратной ассоциации?
Но я не нашел информации об этом.
Комментарии:
1. опечатка .. и я подумал, какую конфигурацию вам не хватает 🙂
2. @Shaharyar, ты что-нибудь знаешь об этом свойстве? почему он создает автоматическую обратную ассоциацию?