Welcome to this in-depth tutorial on querying with associations using Sequelize! In this lesson, we’ll explore two main approaches:
include key to query for related dataThink of associations as relationships between people. Just like you might use a family tree to find out who is related to whom, Sequelize associations help you navigate relationships between data in your database.
Before we dive into Sequelize’s association magic, let’s review how you can fetch related data using basic Sequelize finder methods:
findOnefindAllfindByPkThese methods are like using a phone book to find someone’s contact information—you search for a name and get back the corresponding details. For more complex queries involving conditions (SELECT and WHERE), refer back to earlier lessons on Sequelize.
Sequelize provides two powerful approaches to fetch related data when associations are set up between models:
When you define an association, Sequelize automatically generates “getter” methods on your models. These methods let you retrieve related records directly.
Example with belongsTo Association:
// Assume a Cat belongs to an Owner
const cat = await Cat.findByPk(id); // Find a cat by its primary key
const owner = await cat.getOwner(); // Sequelize auto-generates getOwner()
// 'owner' now contains the data for the cat's single owner
This is similar to asking, "Who is this cat's owner?" and immediately getting the answer.
Example with hasMany or belongsToMany Association:
// Assume a Cat has many Toys
const cat = await Cat.findByPk(id); // Find a cat by its primary key
const toys = await cat.getToys(); // Sequelize auto-generates getToys()
// 'toys' is now an array of objects containing each toy's details
Here, it's like asking, "What toys does this cat have?" and receiving a list of answers.
include KeyYou can also use the include key in your query options to fetch related data in one go. This is particularly useful when you want to load both the primary data and its related records together.
Using include with a belongsTo Association:
const cats = await Cat.findAll({
where: { name: 'Lucy' },
include: Owner // Include the related Owner data
});
console.log(cats[0].Owner); // Logs the Owner object for the first matching cat
In this scenario, each cat object in the returned array will have an Owner key (note the singular form) that holds the owner’s information. It’s as if every cat record comes with its own mini-profile of its owner.
Using include with hasMany or belongsToMany Associations:
const cats = await Cat.findAll({
where: { name: 'Michelle' },
include: Toys // Include the related Toys data
});
console.log(cats[0].Toys); // Logs an array of toy objects for the first matching cat
Each cat object will now include a Toys key (in plural form) with an array of related toy objects. Imagine each cat record as a scrapbook that not only holds cat details but also a collection of its favorite toys.
Let's break down a practical scenario:
Suppose you’re building an app that tracks pets and their belongings. Without associations, you’d have to perform multiple queries to stitch together the pet information and its related data, like a jigsaw puzzle where you manually connect each piece.
With Sequelize associations, you simply define the relationships in your models, and then use either the generated getter methods or the include key. This automates the process—like having a pre-sorted box of puzzle pieces that fit perfectly together.
Understanding when to use each approach is key:
belongsTo association with its get method or include is perfect.hasMany/belongsToMany associations with their corresponding methods are the way to go.In this lesson, we covered:
getOwner, getToys, etc.) based on the type of association.include key in your queries to automatically load related data.belongsTo and hasMany associations.This knowledge opens up a range of possibilities in designing and querying complex data relationships in your applications. For further exploration, consider:
attributes, where, or even nested include calls.hasOne and self-referential associations.