We need to work with a database containing cats and toys, implementing several endpoints that perform various aggregation operations. Let's break down what we need to accomplish:
The main tasks are:
Let's approach this step by step:
// GET /toys endpoint
app.get('/toys', async (req, res, next) => {
// Load all toys first
const allToys = await Toy.findAll();
// Calculate statistics using Sequelize aggregation methods
const toysCount = await Toy.count();
const toysMinPrice = await Toy.min('price');
const toysMaxPrice = await Toy.max('price');
const toysSumPrice = await Toy.sum('price');
res.json({
toysCount,
toysMinPrice,
toysMaxPrice,
toysSumPrice,
allToys
});
});
In this first endpoint, we're using Sequelize's built-in aggregation methods. Think of these like specialized calculators - each one performs a specific mathematical operation on our data:
// GET /cats/:id/toys endpoint
app.get('/cats/:id/toys', async (req, res, next) => {
// First query: Get aggregated toy data
const catToysAggregateData = await Cat.findByPk(req.params.id, {
include: {
model: Toy,
attributes: []
},
attributes: [
[sequelize.fn('COUNT', sequelize.col('Toys.id')), 'toyCount'],
[sequelize.fn('AVG', sequelize.col('Toys.price')), 'averageToyPrice'],
[sequelize.fn('SUM', sequelize.col('Toys.price')), 'totalToyPrice']
],
raw: true
});
// Second query: Get cat with its toys
const cat = await Cat.findByPk(req.params.id, {
include: { model: Toy }
});
// Format the response
const catData = cat.toJSON();
// Add aggregate data to cat object
catData.toyCount = catToysAggregateData.toyCount;
catData.averageToyPrice = catToysAggregateData.averageToyPrice;
catData.totalToyPrice = catToysAggregateData.totalToyPrice;
res.json(catData);
});
This endpoint demonstrates a more complex use of aggregations. We're using SQL functions through Sequelize to calculate statistics. Think of it like a spreadsheet where we're:
// GET /data-summary endpoint
app.get('/data-summary', async (req, res, next) => {
// Get total counts
const totalNumberOfCats = await Cat.count();
const totalNumberOfToys = await Toy.count();
// Get toy summary statistics
const toySummary = await Toy.findAll({
attributes: [
[sequelize.fn('AVG', sequelize.col('price')), 'averagePriceOfAToy'],
[sequelize.fn('SUM', sequelize.col('price')), 'totalPriceOfAllToys'],
[sequelize.fn('MAX', sequelize.col('price')), 'maximumToyPrice'],
[sequelize.fn('MIN', sequelize.col('price')), 'minimumToyPrice']
],
raw: true
});
// Get expensive toy statistics
const expensiveToySummary = await Toy.findAll({
where: {
price: { [Op.gt]: 55 }
},
attributes: [
[sequelize.fn('AVG', sequelize.col('price')), 'averagePriceOfAnExpensiveToy']
],
raw: true
});
res.json({
totalNumberOfCats,
totalNumberOfToys,
toySummary,
expensiveToySummary
});
});
Sequelize provides several built-in methods for aggregating data. These are like specialized tools in your toolbox:
For more complex aggregations, we can use SQL functions through sequelize.fn(). This is like having access to Excel formulas in your database queries:
When working with Sequelize models, the toJSON() method is crucial. Think of it like converting a complex object (like a Swiss Army knife) into a simple one (like a regular knife) - it removes all the extra Sequelize-specific features and gives you a plain JavaScript object.
These aggregation techniques are commonly used in real-world applications:
When working with aggregations, keep these performance tips in mind: