Reputation: 4999
I am creating two models, the first one is User
and the second one is Portfolio
. When a user is creating a Portfolio
(where a user can only have one Portfolio
), I want it to have reference to the user who is creating it, and every time that user's data is fetched, I want it to also fetching their portfolio data if any.
I am trying to use hasOne
to create portfolio_id
inside User
tables, with the skeleton generated using sequelize init
command, but it is not working. I cannot find a column the name protfolio_id
if I don't put it inside the user migration file. Is that how it is supposed to be?
How should I design the models? Should I include the portfolio_id
in User
tables and include user_id
in Portfolio
table, or is there a best way to do it?
And which associations method should I use, hasOne or belongsTo?
Upvotes: 0
Views: 6221
Reputation: 896
First of all make sure that you are calling Model.associate
for each model. This will run queries for all the relationships.
You can define the relationships in the associate method as follows:
// user.js (User Model definition)
module.exports = (sequelize, dataTypes) => {
const { STRING } = dataTypes
const User = sequelize.define("user", {
username: { type: STRING }
})
User.associate = models => {
User.hasOne(models.Portfolio, { foreignKey: "userId" }) // If only one portfolio per user
User.hasMany(models.Portfolio) // if many portfolios per user
}
return User
}
// portfolio.js (Portfolio Model definition)
module.exports = (sequelize, dataTypes) => {
const { STRING } = dataTypes
const Portfolio = sequelize.define("portfolio", {
portfolioName: { type: STRING }
})
Portfolio.associate = models => {
Portfolio.belongsTo(models.User, { foreignKey: "userId" })
}
return Portfolio
}
hasOne stores the foreignKey in the target model. So this relationship will add a foreign key userId
to the Portfolio
model.
belongsTo stores the key in the current model and references the primary key of the target model. In this case the Portfolio.belongsTo
will add userId
in the Portfolio
model which will reference the primary key of User
model.
Notice how both these relationships do the same thing, they add userId to the Portfolio model. Its better to define this in both models for your last use case:
I want it to have reference to the user who is creating it, and every time that user's data is fetched, I want it to also fetching their portfolio data if any.
Accessing related models:
In sequelize fetching a related model together with the main model is called Eager Loading. Read more about it here.
Now for your use case if you want to fetch the portfolio if any, while fetching user, do the following:
var userWithPortfolio = await User.findAll({include: [models.Portfolio]};
// Or you may also use include: {all: true} to include all related models.
var userWithPortfolio = await User.findAll({include: {all: true}};
/*
Output:
userWithPortfolio = {
username: "xyz",
portfolio: {
portfolioName: "xyz"
}
}
*/
Upvotes: 3