Skip to content

Instantly share code, notes, and snippets.

@njb-said
Created October 10, 2017 16:34
Show Gist options
  • Save njb-said/85510182c37ea70a47f70ea72c17299e to your computer and use it in GitHub Desktop.
Save njb-said/85510182c37ea70a47f70ea72c17299e to your computer and use it in GitHub Desktop.
MongoDB pagination
// Terrible code formatting but it works for me
// totalItems = total number of items (across all pages)
// perPage = number of items to show per page
// maxPages = maximum number of pages to show at once
// selectedPage = page currently on
// link = start of link, eg. /search (and then ?page is appended although this code doesn't fully do this)
// reverseSort = if the sortation should be backwards
module.exports.paginate = function(totalItems, perPage, maxPages, selectedPage, link, reverseSort) {
return new Promise(function(resolve, reject) {
var totalPages = Math.ceil(totalItems / perPage);
var hasNext = (selectedPage + 1) <= totalPages;
var hasPrev = (selectedPage - 1) > 0 && (selectedPage - 1) <= totalPages;
if(selectedPage > totalPages) {
return reject();
}
if(totalPages > 1) {
var pagination = {
current: selectedPage,
total: totalPages,
pages: [],
prev: hasPrev ? (selectedPage - 1) : false,
next: hasNext ? (selectedPage + 1) : false
};
var dots = true;
for (var i = 0; i < pagination.total; i++) {
var j = i + 1;
// Bits of this use ajax on frontend to work out link so this is kind of a placeholder
if(j == 1 || j == pagination.total || (j >= pagination.current - maxPages && j <= pagination.current + maxPages)) {
dots = true;
pagination.pages.push({number: j, active: (j == pagination.current), link: link + '?page=' + j});
} else if(dots) {
dots = false;
pagination.pages.push({dots: true});
}
}
var gt = (perPage * (selectedPage - 1));
var lte = gt + perPage;
if(reverseSort) {
gt = (totalItems - gt);
lte = (totalItems - lte);
}
// Returns with a query that can be used in mongo
// Using .skip and .limit is inefficient this is an example
// of range based pagination -- https://docs.mongodb.com/manual/reference/method/cursor.skip/#behavior
// In this case, id is an incrementing id which is used in my case
// Purely for visual reasons for end users
return resolve([pagination, {id: {'$gt' : (reverseSort ? lte : gt), '$lte' : (reverseSort ? gt : lte)}} ]);
} else {
// Pagination disabled
return resolve([false, {}]);
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment