I want to properly setup one-to-one or one-to-many relationship with sequelize and as a matter of fact it all seems to be working just fine if i use either one of hasOne
/ hasMany
or belongsTo
in my model definition.
For example the following associations do create the userId
field on their Targets:
User.hasMany(Email, {
as: 'emails',
foreignKey: 'userId',
})
User.hasOne(Profile, {
as: 'profile',
foreignKey: 'userId',
})
But almost everywhere in official docs i see something like:
Projects.hasMany(Tasks);
Tasks.belongsTo(Projects);
i.e. hasMany
AND belongsTo
are being used together.
Is this really required or it is enough to use just one of them? Any further explanation would be really valuable. Thanks!
The Sequelize hasMany() method is used to create a One-To-Many association between two Sequelize models. For example, suppose you have SQL tables named Countries and Cities in your database. These two tables are related where one country row can have many city rows.
You can make the Task model belongs to the User model by calling the belongsTo() method from the Task model like this: Task. belongsTo(User); The belongsTo() method above will associate the Task model with the User model, adding the UserId attribute to the Task model as the foreign key constraint.
Your solution, along with using include: {all:true} in my findAll query, did the trick. instead of using include: {all:true} in findAll you can use include: {model: models. User, as: 'createdByUser'} , etc. Be sure to use as: in all associations to the same model in your Sequelize model declaration.
To create a One-To-One relationship, the hasOne and belongsTo associations are used together; To create a One-To-Many relationship, the hasMany and belongsTo associations are used together; To create a Many-To-Many relationship, two belongsToMany calls are used together.
Using belongsTo
defines the ownership of the associated models. To explain this in more detail I will refer to the example cited from the tutorials
Project.hasMany(Task);
Task.belongsTo(Project);
Assume that you are no longer interested in the tasks of a deleted project. In that case you would have to delete the tasks manually, had you not defined the belongsTo
association. belongsTo
establishes an ownership of projects over it's tasks and the database will automatically delete the tasks belonging to the deleted project as well. This is called cascading delete
and can chain over multiple tables.
If you run the following code snippet
const Project = sequelize.define('project', {
name: Sequelize.STRING
});
const Task = sequelize.define('task', {
name: Sequelize.STRING
});
Project.hasMany(Task);
Task.belongsTo(Project);
in a sequelize script and watch the output
Executing (default): DROP TABLE IF EXISTS `projects`;
Executing (default): CREATE TABLE IF NOT EXISTS `projects` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL);
Executing (default): PRAGMA INDEX_LIST(`projects`)
Executing (default): DROP TABLE IF EXISTS `tasks`;
Executing (default): CREATE TABLE IF NOT EXISTS `tasks` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `projectId` INTEGER REFERENCES `projects` (`id`) ON DELETE SET NULL ON UPDATE CASCADE);
you will notice the cascading behaviour being set in the creation of the tasks table.
So much said, the final answer is: it depends. The use of belongsTo
can come very handy or will be fatal if you would rather keep the tasks of the deleted project. Only use belongsTo
if it makes sense in the context of your application.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With