我正在用Node.js和mongoose写一个web应用程序。如何对我从.find()调用得到的结果进行分页?我想要一个功能可比的“限制50,100”在SQL。


当前回答

下面的代码是为我工作良好。 你也可以在countDocs查询中添加查找过滤器和user same来获得准确的结果。

export const yourController = async (req, res) => {
  const { body } = req;

  var perPage = body.limit,
  var page = Math.max(0, body.page);

  yourModel
    .find() // You Can Add Your Filters inside
    .limit(perPage)
    .skip(perPage * (page - 1))
    .exec(function (err, dbRes) {
      yourModel.count().exec(function (err, count) { // You Can Add Your Filters inside
        res.send(
          JSON.stringify({
            Articles: dbRes,
            page: page,
            pages: count / perPage,
          })
        );
      });
    });
};

其他回答

在用Rodolphe提供的信息仔细研究了Mongoose API后,我想出了这个解决方案:

MyModel.find(query, fields, { skip: 10, limit: 5 }, function(err, results) { ... });

你可以使用mongoose- pagate -v2。欲了解更多信息,请点击这里

const mongoose         = require('mongoose');
const mongoosePaginate = require('mongoose-paginate-v2');

const mySchema = new mongoose.Schema({
    // your schema code
}); 
mySchema.plugin(mongoosePaginate); 
const myModel = mongoose.model('SampleModel',  mySchema);

myModel.paginate().then({}) // Usage
app.get("/:page",(req,res)=>{
        post.find({}).then((data)=>{
            let per_page = 5;
            let num_page = Number(req.params.page);
            let max_pages = Math.ceil(data.length/per_page);
            if(num_page == 0 || num_page > max_pages){
                res.render('404');
            }else{
                let starting = per_page*(num_page-1)
                let ending = per_page+starting
                res.render('posts', {posts:data.slice(starting,ending), pages: max_pages, current_page: num_page});
            }
        });
});

这是一个版本,我附加到我所有的模型。为了方便,它依赖于下划线,为了性能,它依赖于异步。opts允许使用mongoose语法进行字段选择和排序。

var _ = require('underscore');
var async = require('async');

function findPaginated(filter, opts, cb) {
  var defaults = {skip : 0, limit : 10};
  opts = _.extend({}, defaults, opts);

  filter = _.extend({}, filter);

  var cntQry = this.find(filter);
  var qry = this.find(filter);

  if (opts.sort) {
    qry = qry.sort(opts.sort);
  }
  if (opts.fields) {
    qry = qry.select(opts.fields);
  }

  qry = qry.limit(opts.limit).skip(opts.skip);

  async.parallel(
    [
      function (cb) {
        cntQry.count(cb);
      },
      function (cb) {
        qry.exec(cb);
      }
    ],
    function (err, results) {
      if (err) return cb(err);
      var count = 0, ret = [];

      _.each(results, function (r) {
        if (typeof(r) == 'number') {
          count = r;
        } else if (typeof(r) != 'number') {
          ret = r;
        }
      });

      cb(null, {totalCount : count, results : ret});
    }
  );

  return qry;
}

将它附加到您的模型模式。

MySchema.statics.findPaginated = findPaginated;

在这种情况下,可以将查询页面和/或限制作为查询字符串添加到URL。

例如: ?page=0&limit=25 //这将被添加到您的URL: http:localhost:5000?= 0限制= 25页

因为它是一个字符串,我们需要将它转换为一个数字来进行计算。让我们使用parseInt方法并提供一些默认值。

const pageOptions = {
    page: parseInt(req.query.page, 10) || 0,
    limit: parseInt(req.query.limit, 10) || 10
}

sexyModel.find()
    .skip(pageOptions.page * pageOptions.limit)
    .limit(pageOptions.limit)
    .exec(function (err, doc) {
        if(err) { res.status(500).json(err); return; };
        res.status(200).json(doc);
    });

顺便说一句 分页从0开始