I have defined two table with many-to-many association between them.
create-image-migration.js
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Images', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING
},
...
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Images');
}
};
create-category-migration.js
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Categories', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING
},
...
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Categories');
}
};
Now JOIN table is defined as follows
create-image-category-migration.js
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('ImageCategories', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
imageId: {
type: Sequelize.INTEGER,
allowNull: false,
references: { model: 'Images', key: 'id' }
},
categoryId: {
type: Sequelize.INTEGER,
allowNull: false,
references: { model: 'Categories', key: 'id' }
},
...
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('ImageCategories');
}
};
image-category-model.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const ImageCategory = sequelize.define('ImageCategory', {
imageId: {
type: DataTypes.INTEGER,
allowNull: false,
references: { model: 'Image', key: 'id' },
},
categoryId: {
type: DataTypes.INTEGER,
allowNull: false,
references: { model: 'Category', key: 'id' },
},
...
}, {});
ImageCategory.associate = function(models) {
models.Image.belongsToMany(models.Category, { through: ImageCategory });
models.Category.belongsToMany(models.Image, { through: ImageCategory });
};
return ImageCategory;
};
Now when I run the migration the join table is created with respective column name as specified in migration file i.e. in camel case. But when I run the following bulkCreate command in sequelize to insert data
await db.ImageCategory.bulkCreate([
{ imageId: 'someId', categoryId: topicId, categoryType: 'topic' },
{ imageId: 'someId', categoryId: styleId, categoryType: 'style' },
]);
I am get the following error:
sqlMessage: "Column 'imageId' specified twice",
sql: "INSERT INTO `ImageCategories` (`imageId`,`categoryId`,`categoryType`,`createdAt`,`updatedAt`,`ImageId`) VALUES (5,'22','topic','2022-11-26 08:11:41','2022-11-26 08:11:41',NULL),(5,'27','style','2022-11-26 08:11:41','2022-11-26 08:11:41',NULL);"
},
As we can see here "ImageId" is automatically added by sequelize. So my question is if there is a convention followed by sequelize to name the column name while creating join table since it is not mention anywhere on its documentation.
CodePudding user response:
By default Sequelize generates foreign key names in the pascal case. You do have foreign keys in the junction table that differ with the letter case.
So you just need to indicate foreign keys explicitly in both associations:
ImageCategory.associate = function(models) {
models.Image.belongsToMany(models.Category, { through: ImageCategory, foreignKey: 'imageId' });
models.Category.belongsToMany(models.Image, { through: ImageCategory, foreignKey: 'categoryId' });
};