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


当前回答

这是一个版本,我附加到我所有的模型。为了方便,它依赖于下划线,为了性能,它依赖于异步。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;

其他回答

这是一个示例函数,用于获得具有分页和限制选项的技能模型的结果

 export function get_skills(req, res){
     console.log('get_skills');
     var page = req.body.page; // 1 or 2
     var size = req.body.size; // 5 or 10 per page
     var query = {};
     if(page < 0 || page === 0)
     {
        result = {'status': 401,'message':'invalid page number,should start with 1'};
        return res.json(result);
     }
     query.skip = size * (page - 1)
     query.limit = size
     Skills.count({},function(err1,tot_count){ //to get the total count of skills
      if(err1)
      {
         res.json({
            status: 401,
            message:'something went wrong!',
            err: err,
         })
      }
      else 
      {
         Skills.find({},{},query).sort({'name':1}).exec(function(err,skill_doc){
             if(!err)
             {
                 res.json({
                     status: 200,
                     message:'Skills list',
                     data: data,
                     tot_count: tot_count,
                 })
             }
             else
             {
                 res.json({
                      status: 401,
                      message: 'something went wrong',
                      err: err
                 })
             }
        }) //Skills.find end
    }
 });//Skills.count end

}

您也可以使用下面的代码行

per_page = parseInt(req.query.per_page) || 10
page_no = parseInt(req.query.page_no) || 1
var pagination = {
  limit: per_page ,
  skip:per_page * (page_no - 1)
}
users = await User.find({<CONDITION>}).limit(pagination.limit).skip(pagination.skip).exec()

这段代码将在最新版本的mongo中工作

以上回答是正确的。

只是一个插件,任何人谁是异步等待而不是 承诺! !

const findAllFoo = async (req, resp, next) => {
    const pageSize = 10;
    const currentPage = 1;

    try {
        const foos = await FooModel.find() // find all documents
            .skip(pageSize * (currentPage - 1)) // we will not retrieve all records, but will skip first 'n' records
            .limit(pageSize); // will limit/restrict the number of records to display

        const numberOfFoos = await FooModel.countDocuments(); // count the number of records for that model

        resp.setHeader('max-records', numberOfFoos);
        resp.status(200).json(foos);

    } catch (err) {
        resp.status(500).json({
            message: err
        });
    }
};

也可以用async/await实现结果。

下面的代码示例使用hapi v17和mongoose v5的异步处理程序

{
            method: 'GET',
            path: '/api/v1/paintings',
            config: {
                description: 'Get all the paintings',
                tags: ['api', 'v1', 'all paintings']
            },
            handler: async (request, reply) => {
                /*
                 * Grab the querystring parameters
                 * page and limit to handle our pagination
                */
                var pageOptions = {
                    page: parseInt(request.query.page) - 1 || 0, 
                    limit: parseInt(request.query.limit) || 10
                }
                /*
                 * Apply our sort and limit
                */
               try {
                    return await Painting.find()
                        .sort({dateCreated: 1, dateModified: -1})
                        .skip(pageOptions.page * pageOptions.limit)
                        .limit(pageOptions.limit)
                        .exec();
               } catch(err) {
                   return err;
               }

            }
        }

您可以使用skip()和limit(),但效率非常低。更好的解决方案是对索引字段加上limit()进行排序。 我们在Wunderflats发布了一个小库:https://github.com/wunderflats/goosepage 它用了第一种方法。