Sequelize eager loading is a way to fetch data from multiple tables that have relations between each other.
When you use the eager loading technique, the generated SQL query will have one or more JOIN
clauses.
Let’s see an example of Sequelize eager loading in action.
Suppose you have two tables in your database named Users
and Invoices
as follows:
# Users
+----+-----------+
| id | firstName |
+----+-----------+
| 1 | Nathan |
| 2 | John |
+----+-----------+
#Invoices
+----+--------+--------+
| id | amount | userId |
+----+--------+--------+
| 1 | 300 | 1 |
| 2 | 100 | 2 |
+----+--------+--------+
The Invoices
table stores the UserId
to let viewers know which user is creating the invoice row.
This means each Users
row may have one or more Invoices
rows.
To fetch data from both tables with one query, you need to define the relationship (or association) between the two tables in Sequelize models.
First, create the model for both tables as shown below:
const Invoice = sequelize.define(
"Invoice",
{ amount: Sequelize.INTEGER },
{ timestamps: false }
);
const User = sequelize.define(
"User",
{ firstName: Sequelize.STRING },
{ timestamps: false }
);
Once both models are created, define the correct association between the two models.
In this case, User.hasMany()
and Invoice.belongsTo()
must be defined so that you can fetch both tables from whichever model you choose to query the data:
User.hasMany(Invoice);
Invoice.belongsTo(User);
Now you just need to query the data from the models.
You need to specify the associated model to the main model using the include
option as follows:
const user = await User.findByPk(1, { include: Invoice });
console.log(user.toJSON());
The SQL query generated by the findByPk()
method above will be like this:
SELECT
`User`.`id`,
`User`.`firstName`,
`Invoices`.`id` AS `Invoices.id`,
`Invoices`.`amount` AS `Invoices.amount`,
`Invoices`.`UserId` AS `Invoices.UserId`
FROM
`Users` AS `User`
LEFT OUTER JOIN `Invoices` AS `Invoices`
ON `User`.`id` = `Invoices`.`UserId`
WHERE
`User`.`id` = 1;
Here’s the output of the console log above:
{
id: 1,
firstName: 'Nathan',
Invoices: [
{ id: 1, amount: 300, UserId: 1 }
]
}
You can also query the User
model data from the Invoice
model as follows:
const inv = await Invoice.findOne({ where: { amount: 300 }, include: User });
console.log(inv.toJSON());
The output of the findOne()
method call above will be like this:
{
id: 1,
amount: 300,
UserId: 1,
User: {
id: 1,
firstName: 'Nathan'
}
}
And that’s how the eager loading works in Sequelize. It allows you to generate and execute an SQL script that retrieves data from multiple tables at once.
Here’s the complete JavaScript code from model definition to the console log:
const User = sequelize.define(
"User",
{ firstName: Sequelize.STRING },
{ timestamps: false },
);
const Invoice = sequelize.define(
"Invoice",
{ amount: Sequelize.INTEGER },
{ timestamps: false },
);
User.hasMany(Invoice);
Invoice.belongsTo(User);
const user = await User.findByPk( 1, { include: Invoice });
console.log(user.toJSON());
const inv = await Invoice.findOne( { where: { amount: 300 }, include: User });
console.log(inv.toJSON());
When you have more than two columns, you can put an array inside the include
option of your query method instead of a single Model
object:
const user = await User.findByPk(1, { include: [Role, Invoice, /* ... */] });
If you need it, feel free to use the code examples in your JavaScript project. 😉