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


当前回答

使用猫鼬,快递和翡翠的分页-这里有一个链接到我的博客与更多的细节

var perPage = 10
  , page = Math.max(0, req.params.page)

Event.find()
    .select('name')
    .limit(perPage)
    .skip(perPage * page)
    .sort({
        name: 'asc'
    })
    .exec(function(err, events) {
        Event.count().exec(function(err, count) {
            res.render('events', {
                events: events,
                page: page,
                pages: count / perPage
            })
        })
    })

其他回答

这是一个你可以尝试的例子,

var _pageNumber = 2,
  _pageSize = 50;

Student.count({},function(err,count){
  Student.find({}, null, {
    sort: {
      Name: 1
    }
  }).skip(_pageNumber > 0 ? ((_pageNumber - 1) * _pageSize) : 0).limit(_pageSize).exec(function(err, docs) {
    if (err)
      res.json(err);
    else
      res.json({
        "TotalCount": count,
        "_Array": docs
      });
  });
 });

如果你正在使用mongoose作为一个restful api的源,请看看 ' retify -mongoose'和它的查询。它内置了这个功能。

集合上的任何查询都提供了在这里有用的标头

test-01:~$ curl -s -D - localhost:3330/data?sort=-created -o /dev/null
HTTP/1.1 200 OK
link: </data?sort=-created&p=0>; rel="first", </data?sort=-created&p=1>; rel="next", </data?sort=-created&p=134715>; rel="last"
.....
Response-Time: 37

所以基本上你得到了一个通用服务器,它对集合的查询具有相对线性的加载时间。这是非常棒的,如果你想要进行自己的实现,可以参考一下。

尝试使用mongoose函数进行分页。限制是每页的记录数量和页的数量。

var limit = parseInt(body.limit);
var skip = (parseInt(body.page)-1) * parseInt(limit);

 db.Rankings.find({})
            .sort('-id')
            .limit(limit)
            .skip(skip)
            .exec(function(err,wins){
 });

最好的方法(IMO)是在有限的集合或文档中使用跳过和限制BUT。

要在有限的文档中进行查询,可以使用特定的索引,例如DATE类型字段上的索引。见下图

let page = ctx.request.body.page || 1
let size = ctx.request.body.size || 10
let DATE_FROM = ctx.request.body.date_from
let DATE_TO = ctx.request.body.date_to

var start = (parseInt(page) - 1) * parseInt(size)

let result = await Model.find({ created_at: { $lte: DATE_FROM, $gte: DATE_TO } })
    .sort({ _id: -1 })
    .select('<fields>')
    .skip( start )
    .limit( size )        
    .exec(callback)

有一些很好的答案给出了使用skip()和limit()的解决方案,但是,在某些情况下,我们还需要文档计数来生成分页。以下是我们在项目中所做的:

const PaginatePlugin = (schema, options) => {
  options = options || {}
  schema.query.paginate = async function(params) {
    const pagination = {
      limit: options.limit || 10,
      page: 1,
      count: 0
    }
    pagination.limit = parseInt(params.limit) || pagination.limit
    const page = parseInt(params.page)
    pagination.page = page > 0 ? page : pagination.page
    const offset = (pagination.page - 1) * pagination.limit

    const [data, count] = await Promise.all([
      this.limit(pagination.limit).skip(offset),
      this.model.countDocuments(this.getQuery())
    ]);
    pagination.count = count;
    return { data, pagination }
  }
}

mySchema.plugin(PaginatePlugin, { limit: DEFAULT_LIMIT })

// using async/await
const { data, pagination } = await MyModel.find(...)
  .populate(...)
  .sort(...)
  .paginate({ page: 1, limit: 10 })

// or using Promise
MyModel.find(...).paginate(req.query)
  .then(({ data, pagination }) => {

  })
  .catch(err => {

  })