Pagination In NodeJs: 02 – Cursor based pagination (cursor and limit)

This is my second part of Pagination in NodeJs with MongoDb. Checkout my first post on this where I have implemented  offset based pagination. So, In this I am gonna implemet pagination with Cursors.

So, What’s a cursor? Well cursor is simply remembering/marking the next point from where we have to start fetching data. Let’s say we have 100 data and in one api call we want to fetch only 10 data. So in the first api call we will get first 10 data and when we will get the first 10 data at that time we will remember next data i.e 11th data.  So that while making second api call, we will get data from 11th data and in 3rd api call we will get data from 21st data and so on. Cursor based pagination  should be used  only when cursor value is sequential or timestamp.

 

The example that I am going to implement is going to use timestamp as cursor value. When first api call will occure at that time there will be no cursor value hence at that time we will fetch the most recent values only. Let’s get to the coding part.

 

01. //controller function...
02. exports.getAllPrayers = async (req, res, next) => {
03.  //getting limit & cursor
04.  let limit = parseInt(req.query.limit);
05.  let cursor = parseInt(req.query.cursor);
06.  //if no limit is provided 
07.  if (!limit) { limit = 10; } 
08.
09. //if no cursor is provided then we will take current time as cursor value 
10. if (!cursor) { 
11.    cursor = new Date().toISOString(); 
12. } else { 
13.    cursor = new Date(cursor).toISOString(); 
14. } 
15.
16. try { 
17.
18.    //fetch only those prayers whose creation date is lesser the cursor value 
19.    // we will fetch limit + 1 values so that we can get new cursor value. 
20.    const prayers = await Prayer.find({ 
21.       createdAt: { $lt: cursor,},
22.    }).sort({ createdAt: -1 })
23.    .limit(limit + 1).lean().exec(); 
24.
25.    //if no prayers are available... 
26.    if (!prayers) 
27.      return res.status(400).send({message: "No prayers found!"}); 
28. 
29.    //checking if there is any data left to fetch or we have fetched all data 
30.    const hasMorePrayers = prayers.length === limit + 1; 
31.    let nextCursor = null; 
32. 
33.    if (hasMorePrayers) { 
34.       //remembering next cursor value 
35.       const nextCursorPrayer = prayers[limit - 1]; 
36.       nextCursor = new Date(nextCursorPrayer.createdAt).getTime(); 
37.       prayers.pop(); 
38.    } 
39. 
40.    //our response object... 
41.    const response = { 
42.       limit, 
43.      hasMorePrayers, 
44.       cursor: nextCursor, 
45.       prayersCount: prayers.length, 
46.       prayers, 
47.    }; 
48.    return res.status(200).json({ success: true, data: response }); 
49. } catch (err) { 
50.      console.error(err.message); } 
51. };

So, this is how we can implement pagination using cursor based method. When you will send first request at that time you dont need to provide cursor but limit is required. You can encrypt cursor value if you want more security.