Databases · 07/09 5 min1 hands-on
Pagination that adds up
skip and limit, why you must sort, counting the total, and capping page size.
You never send a whole collection to a client. You send pages.
page 1 → items 1–10 skip 0
page 2 → items 11–20 skip 10
page 3 → items 21–25 skip 20 (a partial page)
So skip = (page - 1) * limit. Using page * limit skips the first page entirely: the most common pagination bug.
The full recipe
const size = Math.min(Math.max(limit, 1), 50); // clamp: ?limit=100000 can't dump the table
const [items, total] = await Promise.all([
Item.find().sort({ createdAt: -1 }).skip((page - 1) * size).limit(size),
Item.countDocuments(),
]);
return { items, page, total, totalPages: Math.ceil(total / size) };
Why sort?
Without sort, the database may return documents in any order, and a different order on each request. Items then repeat or vanish between pages. Always sort, ideally with a unique tiebreaker ({ createdAt: -1, _id: -1 }).
total vs items.length
items.length is the size of this page. The client needs the size of the whole result to draw "Page 2 of 3", so count separately.
Your turn · 1 exercise0/1 solved
Pages that add up
listPage(page, limit) returns { items, page, total, totalPages }. Pages start at 1, items are sorted by n, and limit is capped at 50.
Loading editor…
Next in Databases
Reports with aggregate