简体   繁体   中英

why mongoose query is not working for pagination with skip and limit together?

I wrote a backend code with Node.js Express.js and MongoDB. In the first below code, I created a middleware class in which I can do sorting filtering, and pagination. However, when I tried out the pagination part it is not working I commented on all other alternative variants I came up with. Still, it is not working in the middleware class. But when I tried out in the route itself it is working perfectly. so there is something wrong with the middleware pagination function. Can you help me to fix this issue?

middleware file for sort filter and pagination

class APIFeatures {
  constructor(query, queryString) {
    this.query = query;
    this.queryString = queryString;
  }

  filter() {
    const queryObj = { ...this.queryString };
    const excludedFields = ["page", "sort", "limit", "fields"];
    excludedFields.forEach((el) => delete queryObj[el]);

    // 1B) Advanced filtering
    let queryStr = JSON.stringify(queryObj);
    queryStr = queryStr.replace(
      /\b(gte|gt|lte|lt|search|text)\b/g,
      (match) => `$${match}`
    );

    this.query = this.query.find(JSON.parse(queryStr));

    return this;
  }

  sort() {
    if (this.queryString.sort) {
      const sortBy = this.queryString.sort.split(",").join(" ");
      this.query = this.query.sort(sortBy);
    } else {
      this.query = this.query.sort("-createdAt");
    }

    return this;
  }

  limitFields() {
    if (this.queryString.fields) {
      const fields = this.queryString.fields.split(",").join(" ");
      this.query = this.query.select(fields);
    } else {
      this.query = this.query.select("-__v");
    }

    return this;
  }

  paginate() {
    const page = this.queryString.page || 1;
    const limit = this.queryString.limit || 100;
    const skip = page * limit;

    this.query = this.query.find({}).skip(3).limit(3);
    // this.query = this.query.skip(3).limit(3);
    // this.query = this.query.skip(skip).limit(limit);

    return this;
  }
}
module.exports = APIFeatures;

route or controller file code

  catchAsync(async (req, res, next) => {
    // To allow for nested GET reviews on tour (hack)
    let filter = {};
    if (req.params.tourId) filter = { tour: req.params.tourId };
    // const body = await Model.find({}).skip(3).limit(3);      // this is directly working without any middleware

    const features = new APIFeatures(Model.find(filter), req.query)
      .paginate()
      .filter()
      .sort()
      .limitFields();
    // const doc = await features.query.explain();
    const body = await features.query;
    let totalPages = null;
    if (req.query.page !== "null") {
      const total = await Model.countDocuments({});
      totalPages = Math.ceil(total / req.query.limit);
    }

    // SEND RESPONSE
    res.status(200).json({
      status: "success",
      totalPages,
      data: {
        body,
      },
    });
  });

There is no problem with variable type only it is not giving proper dataset from MongoDB. the limit is working for example everytime I query it gives me correct limit. but when I give skip value the same data or sample comes again in the next pages. as a result some of the data does not come at all. so why it is repeatedly giving the same sample even after skipping.?

paginate() {
const page = this.queryString.page || 1;
const limit = this.queryString.limit || 100;
const skip = page * limit;

this.query = this.query.find({}).skip(3).limit(3);
// this.query = this.query.skip(3).limit(3);
// this.query = this.query.skip(skip).limit(limit);

return this;
}

you have to fix the line above commented line.

this.query = this.query.find({}).skip(skip).limit(limit)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM