Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement pagination and total with mongoose

I have not found how to return total data included in the resultset. Is there any way to return total data? I need to confirm that the correct JSON data is returned.

What I want is to have something like this returned:

total: 40,
page: 1,
pageSize: 3,
books: [
{
    _id: 1,
    title: "达·芬奇密码 ",
    author: "[美] 丹·布朗",
},
{
   _id: 2,
   title: "梦里花落知多少",
   author: "郭敬明",
 },
 {
    _id: 3,
    title: "红楼梦",
    author: "[清] 曹雪芹",
   }
 ]
}

Current code:

router.get('/booksquery', (req, res) => {

var page = parseInt(req.query.page) || 1;
var limit = parseInt(req.query.limit) || 3;

Book.find({})
    .sort({ update_at: -1 })
    .skip((page-1) * limit)
    .limit(limit)
    .exec((err, doc) => {
        if (err) {
            res.json(err)
        } else {
            res.json({
                total: doc.total,
                page: page,
                pageSize: limit,
                books:doc,
            });
        }
    })
 })
like image 815
wen tian Avatar asked Jan 30 '18 12:01

wen tian


People also ask

How do you count in mongoose?

Mongoose | countDocuments() Function The countDocuments() function is used to count the number of documents that match the filter in a database collection.

What is skip and limit in mongoose?

The limit() function in MongoDB is used to specify the maximum number of results to be returned. Only one parameter is required for this function.to return the number of the desired result. Sometimes it is required to return a certain number of results after a certain number of documents. The skip() can do this job.


2 Answers

Probably you could do something like this:

Only if current page index is 0 default and pagination starts with next page, that is 1, your could do .skip(page * limit) make sure .skip() and .limit() gets Number.

  router.get("/booksquery", (req, res) => {
  var page = parseInt(req.query.page) || 0; //for next page pass 1 here
  var limit = parseInt(req.query.limit) || 3;
  var query = {};
  Book.find(query)
    .sort({ update_at: -1 })
    .skip(page * limit) //Notice here
    .limit(limit)
    .exec((err, doc) => {
      if (err) {
        return res.json(err);
      }
      Book.countDocuments(query).exec((count_error, count) => {
        if (err) {
          return res.json(count_error);
        }
        return res.json({
          total: count,
          page: page,
          pageSize: doc.length,
          books: doc
        });
      });
    });
});

from above you will get response like below:

 {
  books: [
    {
      _id: 1,
      title: "达·芬奇密码 ",
      author: "[美] 丹·布朗"
    },
    {
      _id: 2,
      title: "梦里花落知多少",
      author: "郭敬明"
    },
    {
      _id: 3,
      title: "红楼梦",
      author: "[清] 曹雪芹"
    }
  ],
  total: 3,
  page: 0,
  pageSize: 3
}

if you use any condition and over that you want to make query and get result and total on that basics. do it inside var query ={} . and the same query will be used for .count() also. so you can get total count on the basics of that condition.

like image 120
Saikat Chakrabortty Avatar answered Sep 18 '22 10:09

Saikat Chakrabortty


In case someone wants to see this using async/await in 2020, and some random query instead of an empty object. Remember that estimatedDocumentCount does not work using query filters, it needs to be countDocuments by using the query on it. Please check:

  const { userId, page, limit } = req.headers;

  const query = {
    creator: userId,
    status: {
      $nin: ['deleted'],
    },
  };



  const page_ = parseInt(page, 10) || 0;

  const limit_ = parseInt(limit, 10) || 12;

  const books = await BookModel.find(query)
    .sort({ update_at: -1 })
    .skip(page_ * limit_)
    .limit(limit_);

  const count = await BookModel.countDocuments(query);
like image 36
Frederiko Cesar Avatar answered Sep 21 '22 10:09

Frederiko Cesar