Mongoose или mongo skip для pagination возвращают пустой массив? [Дубликат]

В Java все переменные, которые вы объявляете, на самом деле являются «ссылками» на объекты (или примитивы), а не самими объектами.

При попытке выполнить один метод объекта , ссылка просит живой объект выполнить этот метод. Но если ссылка ссылается на NULL (ничего, нуль, void, nada), то нет способа, которым метод будет выполнен. Тогда runtime сообщит вам об этом, выбросив исключение NullPointerException.

Ваша ссылка «указывает» на нуль, таким образом, «Null -> Pointer».

Объект живет в памяти виртуальной машины пространство и единственный способ доступа к нему - использовать ссылки this. Возьмем этот пример:

public class Some {
    private int id;
    public int getId(){
        return this.id;
    }
    public setId( int newId ) {
        this.id = newId;
    }
}

И в другом месте вашего кода:

Some reference = new Some();    // Point to a new object of type Some()
Some otherReference = null;     // Initiallly this points to NULL

reference.setId( 1 );           // Execute setId method, now private var id is 1

System.out.println( reference.getId() ); // Prints 1 to the console

otherReference = reference      // Now they both point to the only object.

reference = null;               // "reference" now point to null.

// But "otherReference" still point to the "real" object so this print 1 too...
System.out.println( otherReference.getId() );

// Guess what will happen
System.out.println( reference.getId() ); // :S Throws NullPointerException because "reference" is pointing to NULL remember...

Это важно знать - когда больше нет ссылок на объект (в пример выше, когда reference и otherReference оба указывают на null), тогда объект «недоступен». Мы не можем работать с ним, поэтому этот объект готов к сбору мусора, и в какой-то момент VM освободит память, используемую этим объектом, и выделит другую.

170
задан Yves M. 26 June 2015 в 15:18
поделиться

19 ответов

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

MyModel.find(query, fields, { skip: 10, limit: 5 }, function(err, results) { ... });
176
ответ дан Thomas 19 August 2018 в 15:57
поделиться
  • 1
    Как насчет & quot; count & quot ;? Вам нужно это знать, сколько страниц есть. – Aleksey Saatchi 2 April 2014 в 11:55
  • 2
    Не масштабируется. – Chris Hinkle 13 May 2014 в 20:49
  • 3
    Объяснение Криса Хинкла, почему это не масштабируется: stackoverflow.com/a/23640287/165330 . – imme 27 May 2014 в 14:43
  • 4
    @ChrisHinkle Это похоже на все СУБД. Комментарий Лекса ниже связанного ответа, кажется, объясняет больше. – csotiriou 29 November 2014 в 11:03
  • 5
    @Avij да. Я использовал идентификатор для этого. то, что вы делаете, отправляет последний идентификатор записей на сервер и получает некоторые записи с идентификатором, большим, чем отправлено. Поскольку Id индексируется так, это будет намного быстрее – George Bailey 21 July 2018 в 07:31

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

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 к своему URL-адресу http. Образец ?page=0&limit=25

BTW Пагинация начинается с 0

22
ответ дан CENT1PEDE 19 August 2018 в 15:57
поделиться
  • 1
    Работает как гладкое желе благодаря @ CENT1PEDE – Suresh Pattu 13 June 2017 в 10:52
  • 2
    Мне нравится гладкое желе. Добро пожаловать :) @SureshPattu – CENT1PEDE 4 July 2017 в 16:44
  • 3
    добавьте `{page: parseInt (req.query.page) || 0, ...}. – imalik8088 24 September 2017 в 10:45
  • 4
    @ imalik8088 Спасибо, однако параметры строки AFAIK обрабатываются автоматически с помощью mongoose. – CENT1PEDE 25 September 2017 в 08:58
  • 5
    Ожидало, но в моем случае он не мог скрыться и показывать мне ошибку – imalik8088 25 September 2017 в 09:28

Вы можете использовать небольшой пакет под названием 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);
  }
}
30
ответ дан Clément Renaud 19 August 2018 в 15:57
поделиться

Пагинация с использованием мангуста, экспресс и нефрита - 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
            })
        })
    })
68
ответ дан Madhusudhan 19 August 2018 в 15:57
поделиться
  • 1
    Благодарим за отправку ответа! Обязательно внимательно прочитайте FAQ по Self-Promotion . Также обратите внимание, что требуется , что вы публикуете отказ от ответственности каждый раз, когда вы ссылаетесь на свой собственный сайт / продукт. – Andrew Barber 12 February 2013 в 00:31
  • 2
    Math.max(0, undefined) вернется undefined. Это сработало для меня: let limit = Math.abs(req.query.limit) || 10; let page = (Math.abs(req.query.page) || 1) - 1; Schema.find().limit(limit).skip(limit * page) – Monfa.red 4 September 2015 в 01:29

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

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

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

query.exec(callback);
47
ответ дан mateeyow 19 August 2018 в 15:57
поделиться
  • 1
    Спасибо за ваш ответ, как обратный вызов с результатом добавил к этому? – Thomas 4 April 2011 в 15:54
  • 2
    execFind (функция (... например: var page = req.param('p'); var per_page = 10; if (page == null) { page = 0; } Location.count({}, function(err, count) { Location.find({}).skip(page*per_page).limit(per_page).execFind(function(err, locations) { res.render('index', { locations: locations }); }); }); – todd 23 June 2011 в 20:49
  • 3
    note: это не будет работать в mongoose , но оно будет работать в mongodb-native-driver. – Jesse 28 March 2012 в 18:47

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

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

Чтобы достичь масштабирования с разбивкой по страницам, объедините предел () вместе с по крайней мере одним критерием фильтра, дата createdOn подходит многим цели.

MyModel.find( { createdOn: { $lte: request.createdOnBefore } } )
.limit( 10 )
.sort( '-createdOn' )
238
ответ дан Rubens Mariuzzo 19 August 2018 в 15:57
поделиться
  • 1
    Но как бы вы получили вторую страницу из этого запроса без пропусков? Если вы просматриваете 10 результатов на страницу и есть 100 результатов, как вы затем определяете значение смещения или пропусков? Вы не отвечаете на вопрос о разбивке на страницы, поэтому вас нельзя «разочаровать», хотя это действительная осторожность. Хотя эта же проблема связана с смещением MySQL, ограничением. Перед возвратом результатов нужно пройти дерево до смещения. Я возьму это с солью, если ваши результирующие наборы будут меньше 1 мила, и не будет достигнуто снижение производительности, используйте skip (). – Lex 9 June 2014 в 01:16
  • 2
    Я новичок, когда дело доходит до мангуста / монгоба, но чтобы ответить на вопрос Лекса, он появляется , что, поскольку результаты упорядочены по '-createdOn', вы замените значение request.createdOnBefore с наименьшим значением createdOn, возвращаемым в предыдущем результирующем наборе, а затем requery. – Terry Lewis 21 August 2014 в 20:54
  • 3
    @JoeFrambach Запрос на основе createdOn кажется проблематичным. Пропуск был встроен по какой-то причине. Документы только предупреждают об ударе производительности циклирования через индекс btree, что имеет место со всеми СУБД. Для пользователей вопрос "что-то сопоставимое MySQL с LIMIT 50 100" .skip точно прав. – Lex 10 September 2014 в 06:42
  • 4
    Хотя интересно, проблема с этим ответом, как отмечает комментарий @Lex, заключается в том, что вы можете только пропустить & quot; forward & quot; или "назад" через результаты - у вас не может быть & quot; страниц & quot; вы можете перейти к (например, страница 1, стр. 2, стр. 3), не создавая несколько запросов последовательных , чтобы выяснить, с чего начать разбиение на страницы, из которых я подозреваю, что в большинстве случаев будет медленнее, чем просто использовать пропускать. Конечно, вам не нужно добавлять возможность переходить на определенные страницы. – Iain Collins 16 March 2015 в 20:12
  • 5
    Этот ответ содержит интересные моменты, но он не отвечает на заданный вопрос. – steampowered 24 July 2015 в 01:28

Наилучший подход (ИМО) заключается в использовании пропусков и ограничений, но в ограниченных коллекциях или документах.

Чтобы сделать запрос в рамках ограниченных документов, мы можем использовать определенный индекс как индекс в поле типа 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)
1
ответ дан Alejandro Teixeira Muñoz 19 August 2018 в 15:57
поделиться

Самый простой плагин для разбивки на страницы.

https://www.npmjs.com/package/mongoose-paginate-v2

Добавить плагин в а затем использовать модельный метод paginate:

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

var mySchema = new mongoose.Schema({ 
    /* your schema definition */ 
});

mySchema.plugin(mongoosePaginate);

var myModel = mongoose.model('SampleModel',  mySchema); 

myModel.paginate().then({}) // Usage
1
ответ дан Arv Ot 19 August 2018 в 15:57
поделиться

Самый простой и быстрый способ: paginate with objectId Example;

Условие начальной нагрузки

condition = {limit:12, type:""};

Возьмите первый и последний объекты ObjectId из данных ответа

Страница next condition

condition = {limit:12, type:"next", firstId:"57762a4c875adce3c38c662d", lastId:"57762a4c875adce3c38c6615"};

Страница next condition

condition = {limit:12, type:"next", firstId:"57762a4c875adce3c38c6645", lastId:"57762a4c875adce3c38c6675"};

В мангусте

var condition = {};
    var sort = { _id: 1 };
    if (req.body.type == "next") {
        condition._id = { $gt: req.body.lastId };
    } else if (req.body.type == "prev") {
        sort = { _id: -1 };
        condition._id = { $lt: req.body.firstId };
    }

var query = Model.find(condition, {}, { sort: sort }).limit(req.body.limit);

query.exec(function(err, properties) {
        return res.json({ "result": result);
});
2
ответ дан byteC0de 19 August 2018 в 15:57
поделиться
**//localhost:3000/asanas/?pageNo=1&size=3**

//requiring asanas model
const asanas = require("../models/asanas");


const fetchAllAsanasDao = () => {
    return new Promise((resolve, reject) => {

    var pageNo = parseInt(req.query.pageNo);
    var size = parseInt(req.query.size);
    var query = {};
        if (pageNo < 0 || pageNo === 0) {
            response = {
                "error": true,
                "message": "invalid page number, should start with 1"
            };
            return res.json(response);
        }
        query.skip = size * (pageNo - 1);
        query.limit = size;

  asanas
            .find(pageNo , size , query)
        .then((asanasResult) => {
                resolve(asanasResult);
            })
            .catch((error) => {
                reject(error);
            });

    });
}
1
ответ дан chetan 19 August 2018 в 15:57
поделиться

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

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
    });

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

8
ответ дан Indra Santosa 19 August 2018 в 15:57
поделиться

Вы можете использовать skip () и limit (), но это очень неэффективно. Лучшим решением будет сортировка по индексированному полю плюс limit (). Мы в Wunderflats опубликовали небольшую библиотеку здесь: https://github.com/wunderflats/goosepage Он использует первый способ.

0
ответ дан Jan Hase 19 August 2018 в 15:57
поделиться
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});
            }
        });
});
0
ответ дан jvitoroc 19 August 2018 в 15:57
поделиться

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

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){
 });
6
ответ дан Karthick 19 August 2018 в 15:57
поделиться

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

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;
5
ответ дан kberg 19 August 2018 в 15:57
поделиться

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

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
      });
  });
 });
12
ответ дан Libu Mathew 19 August 2018 в 15:57
поделиться

Вы можете написать такой запрос.

mySchema.find().skip((page-1)*per_page).limit(per_page).exec(function(err, articles) {
        if (err) {
            return res.status(400).send({
                message: err
            });
        } else {
            res.json(articles);
        }
    });

страница: номер страницы, поступающий от клиента в качестве параметров запроса. per_page: нет результатов, показанных на странице

Если вы используете стек MEAN после сообщения в блоге, он предоставляет большую часть информации для создания разбивки на страницы в конце страницы с использованием бутстрапа с угловым UI и использования методов пропусков и ограничений мангуста в бэкэнд .

см.: https://techpituwa.wordpress.com/2015/06/06/mean-js-pagination-with-angular-ui-bootstrap/

0
ответ дан Manoj Sanjeewa 19 August 2018 в 15:57
поделиться

Если вы используете mongoose в качестве источника для спокойного api, посмотрите « restify-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

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

0
ответ дан Sebastian Schürmann 19 August 2018 в 15:57
поделиться
1
ответ дан Venkatesh Somu 31 October 2018 в 03:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: