How to insert foreign key in sequelize model - node.js

I have a User model and a Houses model in sequelize. I also have a UserHouse model that contains {user_id, house_id}. How do I populate values in the UserHouse model.
I went through the sequelize documentation but could not get a clear idea.
I need to know, how to insert user_id and house_id in UserHouse model.
I also cannot understand what associations should I use between these models.
Any help will be appreciated.
Edited:
One More issue:
I have one more model HouseInfo that stores house_id (foreign key),
how should I store this "house_id" foreign key in db and how should I associate the models.

User.belongsToMany(House, { through: UserHouse });
House.belongsToMany(User, { through: UserHouse });
user.addHouse(house);
house.setUsers([user1, user2])
http://docs.sequelizejs.com/en/latest/docs/associations/#belongs-to-many-associations
http://docs.sequelizejs.com/en/latest/api/associations/belongs-to-many/

Related

Sequelize: Defining Associations

Reading the documentation of Sequelize I'm in some level confused, what Sequelize will provide automatically for us and what we need to explicitly tell it.
I have two models: User and Post. As you have guessed a User can have multiple Posts and a Post belongs only to one User. Setting the respective relationships will look so:
Post.associate = (models) => {
Post.belongsTo(models.users, {
as:'user',
foreignKey: {
name: 'user_id',
allowNull: false
}
}
}
User.associate = (models) => {
User.hasMany(models.posts, {
as:'posts',
onDelete:'CASCADE',
onUpdate:'CASCADE'
}
}
My question is: should I specify the foreignKey one more time when declaring the hasMany association, or it is enough for Sequelize to have the foreignKey in one of the declared relationships between two models (in the example - belongsTo)?
From what I think happens:
Sequelize goes through all your association one by one
If you already provided a foreign key name then fine
Else it will guess/name the foreign key on its own
Like what it says about options.foreignKey in docs e.g. for belongsTo : https://sequelize.org/master/class/lib/model.js~Model.html#static-method-belongsTo (same description for hasOne, hasMany, belongsToMany )
options.foreignKey || string OR object || optional
The name of the foreign key attribute in the source table or an object representing the type definition for the foreign column (see Sequelize.define for syntax). When using an object, you can add a name property to set the name of the column. Defaults to the name of target + primary key of target
If sequelize is guessing your foreignKey names then you will face issues only if your foreignKey name is not matching (tableName + Id) OR (tableName + _ + id)
💡 Hence, better to give foreignKey names on your own to both sides of associations to never face any issues going further.

Sequelize hasOne with BelongsToMany

I have to models DistrictArea and Order which Order must have a DistrictArea instance in it.
so I have done this so far:
Order.hasOne(models.DistricArea)
and in migration file I used this.
queryInterface.addColumn('Orders', 'district_area_id', {
type: Sequelize.INTEGER,
references: {
model: 'DistricAreas',
key: 'id'
}
})
and I have two questions. If we use associated methods in the model , we have to explicitly define these field to our models?
district_area_id: DataTypes.INTEGER
and do I need to define belongsTo in another model (DistricArea)?
the second question is I didn't define any field in DistricArea that associated with Orders. but when I want to use query DistricArea.findAll() it comes with this error:
"column "OrderId" does not exist"
so this is the goal I am trying to achieve:
I need to tell we have many orders that, every order has a
DistricArea.
Yes you still need to define the fields in your model
from what you described above it should be belongsTo instead of hasOne for order model , and hasMany in DistricArea model and then define your sourceKey using your district_area_id field.
Order.belongsTo(models.DistricArea,{foreignKey: 'district_area_id'})
DistricArea.hasMany(models.Order, {foreignKey: 'district_area_id', sourceKey: 'id'})
after this , in DistricArea.findAll() you would get all DistricArea and then inside you will have a Order array which contain every order for each DistricArea, or in a Order.findAll() call you will see all orders with a field district_area_id

referencing a model that hasn't been created, avoid the error: relation "TABLENAME" does not exist

I am very new to sequelize and postgresql. I looked a lot for an answer to this issue but I couldn't find anything related to my it. If this question is has an answer in another post I apologize for repeating and I'll gladly refer to the other post and remove my post from here.
At the beginning I did:
sequelize model:generate --name user --attributes username:string,email:string,password:string,collection_id:INTEGER
where collection_id references another table ID. I did the same for the collection table:
sequelize model:generate --name collection --attributes plant_id:integer,user_id:integer
in my models I updated the association
in the collection model I added:
models.collection.belongsTo(models.user, {foreignKey: 'user_id'})
and in the user model I added:
models.user.hasOne(models.collection, {foreignKey: 'collection_id'})
And in the migration files I added:
user_id: {
type: Sequelize.INTEGER,
references: {
model: {
tableName: 'user'
}
}
}
collection_id: {
type: Sequelize.INTEGER,
references: {
model: {
tableName: 'collection'
}
}
}
in their respective files. Now the issue here is that sequelize is trying to migrate the user model before the collection model, however the later is referenced in the first model and I am getting this error "relation "collection" does not exist" which only makes sense. Now if I removed the reference, is there a way to add it later after I migrate?
reference sets a foreign key on the table under the hood. But you can't have 2 tables with foreign keys pointing to each other (circular reference).
You set a foreign key on the "child" table which points to the "parent" table. In your case, if collection belongs to user then collection is "child".
You can read this paragraph from Sequalize docs with some details about the difference between hasOne and belongsTo (and read about those associations in Sequalize separately as well). {foreignKey: 'collection_id'} which you pass to hasOne method is actually supposed to be in collections table (target model), means in your case it doesn't make sense and should be like this instead:
models.user.hasOne(models.collection, {foreignKey: 'user_id'})
So, you don't need collection_id column in your user table, can safely remove it.

sequelize association explanation on docs

while reading sequelize doc association part, explanation below really confuses me
hasOne and belongsTo insert the association key in different models
from each other. hasOne inserts the association key in target model
whereas belongsTo inserts the association key in the source model.
and also,
Player.belongsTo(Team); // Will add a teamId attribute to Player to hold the primary key value for Team
it seems that if I set relation between two models, sequelize automatically adds foreign key to the target model.
but according to the article,
https://lorenstewart.me/2016/09/12/sequelize-table-associations-joins/z
we have to manually add foreign key to the model file.
which one is right..?
it has been a while since I questioned about this issue.
Any detailed explanation would really be appreciated.
Any recommended articles about sequelize association to read would also be appreciated since sequelize doc seems not that kind for ORM beginners.
Actually it depends on how are you creating your tables. Via sync or via migrations.
For example
const User = sequelize.define('user', {
username: Sequelize.STRING,
});
const Address = sequelize.define('add', {
address: Sequelize.STRING,
});
User.hasOne(Address);
sequelize.sync({ force: true })
.then(() => User.create({
username: 'test'
}))
.then(item => {
console.log(item.dataValues.itemPrice);
});
This will create a userId field in the database
Note that I am use sync. However if you are using migrations, you would have to create this on your own.
PS: Its better to use migrations instead of sync.

Multiple relation n:n to one table in sequelize

I am using Sequelize for PostgresSQL. For example: I've got two tables Friendship and User. To make friendship possible for every user, I've got two relations n:n.
Associations in Sequelize
User.hasMany(Friendship,
{
as: "friendshipsAsked",
foreignKey: "asked_user_id",
joinTableName: "friendship"
});
User.hasMany(Friendship,
{
as: "friendshipsAsking",
foreignKey: "asking_user_id",
joinTableName: "friendship"
});
Friendship.belongsTo(User,
{
...
});
Friendship.belongsTo(User,
{
...
});
My biggest problem is querying friendships for user. When I've got user model, I have to get user.getFriendshipsAsking() and user.getFriendshipsAsked() and then merge both.
Is there any possibility to change relations so I can have user.getFriendships() in SQL such that it will perform like SELECT * FROM frienships WHERE requesting_user_id = 'user.id' OR requested_user_id = 'user.id'?
I would like to have a better solution to model friendship between users in the database?

Resources