My problem is that when I execute this code:
const task = await db.tasks.findByPk(1)
const user = await db.users.findByPk(4)
await user.setTasks(task)
This happens:
Executing (default): SELECT `tasks`.`id`, `tasks`.`start_date` FROM `tasks` AS `tasks` WHERE `tasks`.`id` = '1';
Executing (default): SELECT `id`, `name`, `surname`, `email`, `role` FROM `users` AS `users` WHERE `users`.`id` = '4';
Executing (default): SELECT `id`, `task_id`, `user_id` FROM `users_tasks` AS `users_tasks` WHERE `users_tasks`.`user_id` = 4;
Executing (default): DELETE FROM `users_tasks` WHERE `user_id` = 4 AND `task_id` IN (2)
Executing (default): INSERT INTO `users_tasks` (`id`,`task_id`,`user_id`) VALUES (NULL,1,4);
The user with id 4 had a previous association with a task with id 2. The issue is, I want to keep that association! It is perfectly fine for the purpose of my application for a user to be assigned to more tasks (and vice versa).
I would actually say that that's the normal desired behaviour of a many-to-many relationship... why is Sequelize deleting the row on users_tasks
before adding a new one, and how can I prevent this from happening?
Here is my user model:
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define('users', {
id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING(50),
allowNull: false
},
surname: {
type: DataTypes.STRING(50),
allowNull: false
},
email: {
type: DataTypes.STRING(256),
allowNull: false
},
}, {
tableName: 'users',
timestamps: false,
})
User.associate = function (models) {
User.belongsToMany(models.tasks, {through: 'users_tasks', foreignKey: 'user_id'})
}
return User
}
Here is my task model:
module.exports = function(sequelize, DataTypes) {
var Task = sequelize.define('tasks', {
id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
start_date: {
type: DataTypes.DATE,
allowNull: true,
},
}, {
tableName: 'tasks',
timestamps: false
})
Task.associate = function (models) {
Task.belongsToMany(models.users, {through: 'users_tasks', foreignKey: 'task_id'})
}
return Task
}
And here is my join table:
module.exports = function(sequelize, DataTypes) {
return sequelize.define('users_tasks', {
id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
task_id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
references: {
model: 'tasks',
key: 'id'
}
},
user_id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
references: {
model: 'users',
key: 'id'
}
}
}, {
tableName: 'users_tasks',
timestamps: false
})
}
Do I need to change something on the models definitions, or do I need to change something in the way I call setTasks
? Or else, what do I need to do? Why is Sequelize enforcing this weird and unwanted behaviour of deleting previously existing associations?
I found out that I should be using add
instead of set
if I want to keep the preexisting relations.
So, the correct way of achieving the result I want is this:
const task = await db.tasks.findByPk(1)
const user = await db.users.findByPk(4)
await user.addTasks(task)