Building a Pagination API with MongoDB
Building a Pagination API with MongoDB
Overview
Pagination is a common technique used to divide large datasets into smaller, more manageable chunks (pages). This is particularly useful for APIs that return data lists, such as blog posts, products, or user records.
MongoDB supports efficient pagination using queries with limit() and skip(), or more efficiently, using range-based pagination (also known as cursor-based pagination) with a sorting key.
Approaches to Pagination
1. Offset-based Pagination (Skip & Limit)
This is the simplest and most common approach.
Example Query:
javascript
Copy
Edit
db.users.find().skip((page - 1) * pageSize).limit(pageSize);
API Example (Node.js with Express):
javascript
Copy
Edit
app.get('/users', async (req, res) => {
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 10;
const skip = (page - 1) * limit;
const users = await db.collection('users')
.find({})
.skip(skip)
.limit(limit)
.toArray();
res.json({ page, limit, users });
});
Pros:
Easy to implement.
Works well for small datasets.
Cons:
Performance decreases with large offsets.
Not stable if documents are added or removed between requests (inconsistent results).
2. Cursor-based Pagination (Range-based)
This is more efficient for large datasets and real-time applications.
How It Works:
Sort documents by a unique, indexed field (like _id or a timestamp).
Keep track of the last item seen (cursor).
Fetch the next page based on that field.
Example Query:
javascript
Copy
Edit
db.users.find({ _id: { $gt: lastId } }).limit(pageSize);
API Example:
javascript
Copy
Edit
app.get('/users', async (req, res) => {
const limit = parseInt(req.query.limit) || 10;
const lastId = req.query.lastId;
const query = lastId ? { _id: { $gt: new ObjectId(lastId) } } : {};
const users = await db.collection('users')
.find(query)
.sort({ _id: 1 })
.limit(limit)
.toArray();
const nextCursor = users.length > 0 ? users[users.length - 1]._id : null;
res.json({ users, nextCursor });
});
Pros:
High performance.
Consistent and reliable for dynamic data.
Cons:
Slightly more complex to implement.
Only supports forward navigation unless extra logic is added.
Best Practices for Pagination APIs
Always sort results (e.g., by _id, timestamp, or other indexed field).
Use indexes to improve query performance.
Return metadata like totalCount, currentPage, nextCursor, etc.
Avoid exposing raw _id values in public APIs if possible.
Handle empty results and edge cases gracefully.
Example JSON Response
json
Copy
Edit
{
"users": [
{ "_id": "66500f1c...", "name": "Alice" },
{ "_id": "66500f1e...", "name": "Bob" }
],
"nextCursor": "66500f1e..."
}
Would you like a working code snippet using a specific language like Python (Flask or FastAPI) or a deeper look into cursor vs offset tradeoffs?
Learn MERN Stack Course in Hyderabad
Read More
Visit Our Quality Thought Training in Hyderabad
Comments
Post a Comment