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


当前回答

MongoDB官方博客有一个关于分页的条目,在那里他们解释了为什么“跳过”可能会很慢,并提供了替代方案:https://www.mongodb.com/blog/post/paging-with-the-bucket-pattern--part-1

其他回答

我对这个问题的公认答案感到非常失望。这是无法缩放的。如果你读了游标上的小字。跳过():

cursor.skip()方法通常开销很大,因为它需要服务器从集合或索引的开始处遍历以获得偏移或跳过位置,然后才开始返回结果。随着偏移量(例如上面的pageNumber)的增加,cursor.skip()将变得更慢,更消耗CPU。对于较大的集合,cursor.skip()可能成为IO绑定。

要以可伸缩的方式将limit()与至少一个筛选条件结合起来实现分页,createdOn日期适合多种用途。

MyModel.find( { createdOn: { $lte: request.createdOnBefore } } )
.limit( 10 )
.sort( '-createdOn' )

在这种情况下,可以将查询页面和/或限制作为查询字符串添加到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开始

使用这个简单的插件。

https://github.com/WebGangster/mongoose-paginate-v2

安装

NPM安装mongoose- pagate -v2 使用 添加插件到一个模式,然后使用模型paginate方法:

Const mongoose = require('mongoose'); const mongoosePaginate = require(' mongoosePaginate -v2'); const mySchema =新的猫鼬。模式({ /*你的模式定义*/ }); mySchema.plugin (mongoosePaginate); const myModel =猫鼬。模型(SampleModel, mySchema); myModel.paginate().then({}) //使用方法

也可以用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;
               }

            }
        }

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

 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

}