I want to make pagination for my nodejs application. I am using the following code:
static async getAllPaginatedNewsList(p = 1 , s = 10 , type = "user") {
try {
let allNews = [];
if(type === "user"){
allNews = await News.find({news_publish: true}).sort({ news_date: "descending" });
}
else if(type === "admin"){
allNews = await News.find().sort({ news_date: "descending" });
}
const totalItems = allNews.length;
const totalPages = Math.ceil(totalItems/s);
return allNews.skip((p- 1) * s).limit(s);
} catch (error) {
console.log(`Could not fetch news list ${error}`)
}
}
I don't know why there is an error when I want to return the result by allNews.skip((p- 1) * s).limit(s)
by the way the following code works fine:
static async getAllPaginatedNewsList(p = 1 , s = 10 , type = "user") {
try {
let allNews = [];
if(type === "user"){
allNews = await News.find({news_publish: true}).sort({ news_date: "descending" }).skip((p- 1) * s).limit(s);
}
else if(type === "admin"){
allNews = await News.find().sort({ news_date: "descending" }).skip((p- 1) * s).limit(s);
}
//const totalItems = allNews.length;
//const totalPages = Math.ceil(totalItems/s);
return allNews;
} catch (error) {
console.log(`Could not fetch news list ${error}`)
}
}
but I don't want to use the second solution, by using than I should make two times database query to find for example the totalItems value. What's wrong with my code and how may I solve it?
CodePudding user response:
To implement pagination you need to know the total records present in your database.
What you can do is simply use a count function of mongoose to find total records and then you can find out how many pages you will have to display based on records per page.
You are trying to use a skip
function on the result of the query, that is wrong. you need to use it like you have done in the second part of your code.
Fetching all the records from DB and then counting the result is a bad practice as it's not an efficient use of your memory.
You just need to know total records so doing one extra count query is better than fetching all data and then filtering results to display the required data.
Mongoose gives you a function countDocuments
you can use it to get total number of records in your collection.
static async getAllPaginatedNewsList(p = 1 , s = 10 , type = "user") {
try {
let allNews = [];
let totalItems = 0;
if(type === "user"){
let where = {
news_publish: true
}
[totalItems, allNews] = await Promise.all([
News.countDocuments(where),
News.find(where).sort({ news_date: "descending" }).skip((p- 1) * s).limit(s)
]);
} else if(type === "admin"){
[totalItems, allNews] = await Promise.all([
News.countDocuments(),
News.find().sort({ news_date: "descending" }).skip((p- 1) * s).limit(s)
]);
}
const totalPages = Math.ceil(totalItems/s);
return allNews;
} catch (error) {
console.log(`Could not fetch news list ${error}`)
}
}