When working with paginated data, users often need to know the bigger picture. Imagine reading a book - even when you're on page 50, you want to know how many total pages there are. In our API, we need to provide:
Let's implement this step by step in our students endpoint:
// GET /students
router.get('/', async (req, res) => {
// Get pagination parameters
let page = parseInt(req.query.page) || 1;
let size = parseInt(req.query.size) || 10;
// Initialize result object
const result = {
rows: [],
count: 0,
pageCount: 0,
page: page
};
try {
// Get total count of students
const totalCount = await Student.count();
result.count = totalCount;
// Calculate total pages
result.pageCount = Math.ceil(totalCount / size);
// If valid pagination parameters
if (page >= 1 && size >= 1 && size <= 200) {
const offset = (page - 1) * size;
// Get paginated results
const students = await Student.findAll({
limit: size,
offset: offset,
order: [['lastName', 'ASC'], ['firstName', 'ASC']]
});
result.rows = students;
} else if (page === 0 && size === 0) {
// Special case: get all results
const students = await Student.findAll({
order: [['lastName', 'ASC'], ['firstName', 'ASC']]
});
result.rows = students;
result.page = 1;
} else {
// Invalid parameters
return res.status(400).json({
errors: [{ message: 'Requires valid page and size params' }],
count: totalCount,
pageCount: Math.ceil(totalCount / 10) // Using default size
});
}
return res.json(result);
} catch (err) {
console.error(err);
res.status(500).json({
errors: [{ message: 'Server error' }],
count: 0,
pageCount: 0
});
}
});
Think of aggregation like taking inventory in a library:
pageCount = Math.ceil(totalCount / size)
Example calculations:
- 267 total records, 10 per page:
pageCount = Math.ceil(267 / 10) = 27 pages
- 267 total records, 12 per page:
pageCount = Math.ceil(267 / 12) = 23 pages
- 267 total records, 150 per page:
pageCount = Math.ceil(267 / 150) = 2 pages
A successful response will look like:
{
"count": 267, // Total number of records
"rows": [...], // Current page of data
"pageCount": 27, // Total number of pages
"page": 1 // Current page number
}
This pattern appears in many familiar interfaces:
Test the following scenarios:
Watch out for these common issues:
Consider these optimization techniques:
When troubleshooting pagination and aggregation: