Practicing Data Queries with Sequelize

Understanding the Problem

We need to retrieve specific data about puppies from our database using Sequelize. Think of this like being a librarian who needs to find different books based on various criteria. Just as a librarian might need to find all books, books by a specific author, or books meeting certain conditions, we need to query our database in different ways to find puppies based on different criteria.

Breaking Down the Queries

Let's examine each type of query we need to build, understanding them like different ways to search through our puppy library:

Finding All Records

Like looking at every book on the shelf, we'll start with retrieving all puppies:

// Route to get all puppies, ordered by name
app.get('/puppies', async (req, res, next) => {
    let allPuppies = await Puppy.findAll({
        // Just like alphabetizing books on a shelf
        order: [['name', 'ASC']]
    });
    res.json(allPuppies);
});

Finding Records with Specific Conditions

Similar to finding all books about a specific topic, we can find puppies meeting certain criteria:

// Route to get microchipped puppies
app.get('/puppies/chipped', async (req, res, next) => {
    let chippedPuppies = await Puppy.findAll({
        where: {
            microchipped: true
        },
        // Primary sort by age, secondary sort by name
        order: [
            ['ageYrs', 'DESC'],
            ['name', 'ASC']
        ]
    });
    res.json(chippedPuppies);
});

Finding One Record by Name

Like finding a specific book by its title, we can find a puppy by name:

// Route to find one puppy by name
app.get('/puppies/name/:name', async (req, res, next) => {
    let puppyByName = await Puppy.findOne({
        where: {
            name: req.params.name
        }
    });
    res.json(puppyByName);
});

Finding One Record by Primary Key

Similar to finding a book by its unique ISBN number:

// Route to find one puppy by ID
app.get('/puppies/:id', async (req, res, next) => {
    let puppyById = await Puppy.findByPk(req.params.id);
    res.json(puppyById);
});

Using Complex Conditions

Like finding books that match multiple criteria, we can use more complex queries:

// Route to find shepherd breeds
app.get('/puppies/shepherds', async (req, res, next) => {
    let shepherds = await Puppy.findAll({
        where: {
            breed: {
                [Op.like]: '%Shepherd'  // Ends with 'Shepherd'
            }
        },
        order: [['name', 'DESC']]  // Reverse alphabetical order
    });
    res.json(shepherds);
});

Combining Multiple Conditions

Like finding books that are both short and recently published:

// Route to find young, small puppies
app.get('/puppies/tinybabies', async (req, res, next) => {
    let tinyBabyPuppies = await Puppy.findAll({
        where: {
            ageYrs: { [Op.lt]: 1 },     // Less than 1 year old
            weightLbs: { [Op.lte]: 20 }  // 20 pounds or lighter
        },
        order: [
            ['ageYrs', 'ASC'],     // Youngest first
            ['weightLbs', 'ASC']    // Then lightest first
        ]
    });
    res.json(tinyBabyPuppies);
});

Understanding Key Concepts

Query Methods

Sequelize provides several main methods for retrieving data:

// Finding multiple records
Puppy.findAll()    // Returns array of all matching records
Puppy.findOne()    // Returns first matching record

// Finding by primary key
Puppy.findByPk()   // Returns record matching primary key

// Other useful methods
Puppy.count()      // Returns count of matching records
Puppy.findOrCreate() // Creates record if not found
Puppy.findAndCountAll() // Returns both records and count

The Where Clause

The where clause in Sequelize is like a filter for your records. You can use it in several ways:

// Simple equality
where: { name: 'Cooper' }

// Using operators
where: {
    ageYrs: { [Op.lt]: 1 }    // Less than
    breed: { [Op.like]: '%Shepherd' }  // Pattern matching
}

// Combining conditions
where: {
    [Op.and]: [
        { ageYrs: { [Op.lt]: 1 } },
        { weightLbs: { [Op.lte]: 20 } }
    ]
}

Ordering Results

Order is specified as an array of arrays, each inner array containing the column name and direction:

// Single sort
order: [['name', 'ASC']]

// Multiple sort criteria
order: [
    ['ageYrs', 'DESC'],
    ['name', 'ASC']
]

Common Operators

Sequelize provides many operators for complex queries:

// Comparison operators
[Op.eq]: 3                  // = 3
[Op.ne]: 20                 // != 20
[Op.lt]: 1                  // < 1
[Op.lte]: 20               // <= 20
[Op.gt]: 5                 // > 5
[Op.gte]: 6                // >= 6

// String operators
[Op.like]: '%dog'          // LIKE '%dog'
[Op.startsWith]: 'Pup'     // LIKE 'Pup%'
[Op.endsWith]: 'py'        // LIKE '%py'

// Array operators
[Op.in]: [1, 2]            // IN [1, 2]
[Op.notIn]: [1, 2]         // NOT IN [1, 2]

Best Practices

When writing queries, remember to:

Practical Tips

Here are some practical tips for working with Sequelize queries:

Further Learning

To deepen your understanding, try: