Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between HasOne and BelongsTo in Sequelize ORM

I am developing a sails.js app with sequelize ORM. I am a little confused as to when BelongsTo and HasOne need to be used.

The documentation states that :

BelongsTo associations are associations where the foreign key for the one-to-one relation exists on the source model.

HasOne associations are associations where the foreign key for the one-to-one relation exists on the target model.

Is there any other difference apart from the the place where these are specified? Does the behavior still continue to be the same in either cases?

like image 545
Jaseem Abbas Avatar asked Jan 02 '16 11:01

Jaseem Abbas


People also ask

What is the difference between belongsTo and hasOne?

The only difference between hasOne and belongsTo is where the foreign key column is located. Let's say you have two entities: User and an Account. In short hasOne and belongsTo are inverses of one another - if one record belongTo the other, the other hasOne of the first.

What is the difference between hasMany and belongsTo?

belongsTo(B) association means that a One-To-One relationship exists between A and B , with the foreign key being defined in the source model ( A ). The A. hasMany(B) association means that a One-To-Many relationship exists between A and B , with the foreign key being defined in the target model ( B ).

How do you use belongsTo in Sequelize?

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.

How do you include two models in Sequelize?

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.


2 Answers

This is more universal problem.

The main difference is in semantic. you have to decide what is the relationship (Some silly example):

Man has only one right arm. Right arm belongs to one man.

Saying it inversely looks a little weird:

Right arm has a man. A man belongs to right arm.

You can have man without right arm. But alone right arm is useless.

In sequelize if RightArm and Man are models, it may looks like:

Man.hasOne(RightArm);      // ManId in RigthArm RightArm.belongsTo(Man);   // ManId in RigthArm 

And as you notice there is also difference in db table structure:

BelongsTo will add the foreignKey on the source where hasOne will add on the target (Sequelize creates new column 'ManId' in table 'RightArm' , but doesn't create 'RightArmId' column in 'Man' table).

I don't see any more differences.

like image 140
Krzysztof Sztompka Avatar answered Sep 21 '22 01:09

Krzysztof Sztompka


I agree with Krzysztof Sztompka about the difference between:

Man.hasOne(RightArm); RightArm.belongsTo(Man); 

I'd like to answer Yangjun Wang's question:

So in this case, should I use either Man.hasOne(RightArm); or RightArm.belongsTo(Man);? Or use them both?

It is true that the Man.hasOne(RightArm); relation and the RightArm.belongsTo(Man); one do the same thing - each of these relations will add the foreign key manId to the RightArm table.

From the perspective of the physical database layer, these methods do the same thing, and it makes no difference for our database which exact method we will use.

So, what's the difference? The main difference lays on the ORM's layer (in our case it is Sequalize ORM, but the logic below applies to Laravel's Eloquent ORM or even to Ruby's Active Record ORM).

Using the Man.hasOne(RightArm); relation, we will be able to populate the man's RightArm using the Man model. If this is enough for our application, we can stop with it and do not add the RightArm.belongsTo(Man); relation to the RightArm model.

But what if we need to get the RightArm's owner? We won't be able to do this using the RightArm model without defining the RightArm.belongsTo(Man); relation on the RightArm model.

One more example will be the User and the Phone models. Defining the User.hasOne(Phone) relation, we will be able to populate our User's Phone. Without defining the Phone.belongsTo(User) relation, we won't be able to populate our Phone's owner (e.g. our User). If we define the Phone.belongsTo(User) relation, we will be able to get our Phone's owner.

So, here we have the main difference: if we want to be able to populate data from both models, we need to define the relations (hasOne and belongsTo) on both of them. If it is enough for us to get only, for example, User's Phone, but not Phone's User, we can define only User.hasOne(Phone) relation on the User model.

The logic above applies to all the ORMs that have hasOne and belongsTo relations.

I hope this clarifies your understanding.

like image 31
Vladyslav Turak Avatar answered Sep 24 '22 01:09

Vladyslav Turak