Как разбить на страницы с помощью Mongoose в Node.js? - PullRequest
194 голосов
/ 04 апреля 2011

Я пишу веб-приложение с Node.js и mongoose.Как я могу разбить на страницы результаты, которые я получаю от звонка .find()?Я хотел бы функциональность, сравнимую с "LIMIT 50,100" в SQL.

Ответы [ 23 ]

255 голосов
/ 13 мая 2014

Я очень разочарован принятыми ответами на этот вопрос. Это не будет масштабироваться. Если вы прочитали мелкий шрифт на cursor.skip ():

Метод cursor.skip () часто является дорогостоящим, поскольку он требует, чтобы сервер прошел от начала коллекции или индекса, чтобы получить смещение или позицию пропуска, прежде чем начать возвращать результат. По мере увеличения смещения (например, pageNumber выше) cursor.skip () будет медленнее и интенсивнее загружать процессор. В больших коллекциях cursor.skip () может стать связанным с IO.

Для масштабирования нумерации страниц объедините limit () и, по крайней мере, один критерий фильтра, дата createOn подходит для многих целей.

MyModel.find( { createdOn: { $lte: request.createdOnBefore } } )
.limit( 10 )
.sort( '-createdOn' )
200 голосов
/ 04 апреля 2011

После более внимательного изучения API Mongoose с информацией, предоставленной Родольфом, я нашел решение:

MyModel.find(query, fields, { skip: 10, limit: 5 }, function(err, results) { ... });
79 голосов
/ 12 февраля 2013

Пагинация с использованием мангуста, экспресса и нефрита - http://madhums.me/2012/08/20/pagination-using-mongoose-express-and-jade/

var perPage = 10
  , page = Math.max(0, req.param('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
            })
        })
    })
53 голосов
/ 04 апреля 2011

Вы можете цепочкой просто так:

var query = Model.find().sort('mykey', 1).skip(2).limit(5)

Выполнить запрос, используя exec

query.exec(callback);
31 голосов
/ 10 октября 2012

Вы можете использовать небольшой пакет под названием Mongoose Paginate , который облегчает это.

$ npm install mongoose-paginate

После того, как в вашем маршруте или контроллере, просто добавьте:

/**
 * querying for `all` {} items in `MyModel`
 * paginating by second page, 10 items per page (10 results, page 2)
 **/

MyModel.paginate({}, 2, 10, function(error, pageCount, paginatedResults) {
  if (error) {
    console.error(error);
  } else {
    console.log('Pages:', pageCount);
    console.log(paginatedResults);
  }
}
31 голосов
/ 07 июня 2016

Лучше поздно, чем никогда.

var pageOptions = {
    page: req.query.page || 0,
    limit: req.query.limit || 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);
    })

В этом случае вы можете добавить запрос page и / или limit в ваш http-адрес. Образец ?page=0&limit=25

КСТАТИ Нумерация страниц начинается с 0

14 голосов
/ 02 февраля 2016

Это пример, который вы можете попробовать,

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
      });
  });
 });
10 голосов
/ 12 марта 2017

Попробуйте использовать функцию мангуста для нумерации страниц. Лимит - это количество записей на странице и номер страницы.

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){
 });
8 голосов
/ 21 октября 2014

Это то, что я сделал с кодом

var paginate = 20;
var page = pageNumber;
MySchema.find({}).sort('mykey', 1).skip((pageNumber-1)*paginate).limit(paginate)
    .exec(function(err, result) {
        // Write some stuff here
    });

Вот как я это сделал.

6 голосов
/ 14 февраля 2013

Вот версия, которую я прикрепляю ко всем моим моделям. Это зависит от подчеркивания для удобства и асинхронности для производительности. Опции позволяют выбирать поля и сортировать их, используя синтаксис мангусты.

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;
...