Как реализовать пагинацию для mongodb в node.js, используя официальный клиент mongodb? - PullRequest
1 голос
/ 03 октября 2019

Я хочу реализовать нумерацию страниц для mongodb в node.js , используя официальный пакет mongodb . Я попытался выяснить в Интернете, но все ссылки основаны на mongoose . Я не хочу использовать мангуст.

Как я могу реализовать нумерацию страниц, используя официальный клиентский API, указанный в
http://mongodb.github.io/node-mongodb-native/3.1/api/

Ответы [ 4 ]

1 голос
/ 03 октября 2019

Использование рекомендуемого подхода к разбиению на страницы с помощью limit () и skip () ( см. Здесь ):

const MongoClient = require('mongodb').MongoClient;
MongoClient.connect('http:localhost:27017').then((client) => {
    const db = client.db(mongo.db);
    db.collection('my-collection').find({}, {limit:10, skip:0}).then((documents) => {
        //First 10 documents
        console.log(documents);
    });


    db.collection('my-collection').find({}, {limit:10, skip:10}).then((documents) => {
        //Documents 11 to 20
        console.log(documents);
    });
});

Вот функция разбиения на страницы:

function studentsPerPage (pageNumber, nPerPage) {
    return db.collection('students').find({}, 
        {
            limit: nPerPage, 
            skip: pageNumber > 0 ? ( ( pageNumber - 1 ) * nPerPage ) : 0
        });
}
0 голосов
/ 16 октября 2019

Подход на основе смещения имеет большой недостаток: если список результатов изменяется между вызовами API, индексы будут сдвигаться и приводить к тому, что элемент либо возвращается дважды, либо пропускается и никогда не возвращается

Эта проблема демонстрируется при https://www.sitepoint.com/paginating-real-time-data-cursor-based-pagination/

Подход на основе времени нумерации страниц будет немного лучше, потому что результаты больше не пропускаются. Если вы запросите первую страницу, а затем новый элемент будет удален, результаты на второй странице не будут сдвинуты, и все в порядке. Однако этот подход имеет существенный недостаток: что, если одновременно будет создано более одного элемента?

Лучше всего будет использовать Пагинация на основе курсора
Что можетбыть реализованным с использованием любого поля в коллекции, которое является Уникальным, Заказным и Неизменным .

_id удовлетворяет всем Уникальным, заказным и неизменным условиям. На основе этого поля мы можем отсортировать и вернуть результат страницы с _id последнего документа в качестве последовательности для последующего запроса.

curl https://api.mixmax.com/items?limit=2

const items = db.items.find({}).sort({
   _id: -1
}).limit(2);

const next = items[items.length - 1]._id
res.json({ items, next })

когда пользователь хочет получить вторую страницу, он передает курсор (как следующий) на URL: curl https://api.mixmax.com/items?limit=2&next=590e9abd4abbf1165862d342

const items = db.items.find({
  _id: { $lt: req.query.next }
}).sort({
   _id: -1
}).limit(2);

const next = items[items.length - 1]._id
res.json({ items, next })

Если мы хотим вернуть результаты в другом порядке, например, в дату элемента, мы добавим sort=launchDate к строке запроса. curl https://api.mixmax.com/items?limit=2&sort=launchDate

const items = db.items.find({}).sort({
   launchDate: -1
}).limit(2);

const next = items[items.length - 1].launchDate;
res.json({ items, next })

Для последующего запроса страницы
curl https://api.mixmax.com/items?limit=2&sort=launchDate&next=2017-09-11T00%3A44%3A54.036Z

const items = db.items.find({
  launchDate: { $lt: req.query.next }
}).sort({
   _id: -1
}).limit(2);

const next = items[items.length - 1].launchDate;
res.json({ items, next });

Если мы запустили несколько элементов в один и тот же день и время? Теперь наше launchDate поле больше не является уникальным и не удовлетворяет Уникальным, Заказным и Неизменным . условие. Мы не можем использовать его как поле курсора. Но мы могли бы использовать два поля для генерации курсора. Поскольку мы знаем, что поле _id в MongoDB всегда удовлетворяет вышеуказанным трем условиям, мы знаем, что если мы используем его вместе с нашим полем launchDate, комбинация этих двух полей будетудовлетворить требования и могут быть вместе использованы в качестве поля курсора. curl https://api.mixmax.com/items?limit=2&sort=launchDate

const items = db.items.find({}).sort({
   launchDate: -1,
  _id: -1 // secondary sort in case there are duplicate launchDate values
}).limit(2);

const lastItem = items[items.length - 1];
// The cursor is a concatenation of the two cursor fields, since both are needed to satisfy the requirements of being a cursor field
const next = `${lastItem.launchDate}_${lastItem._id}`;
res.json({ items, next });

Для запроса следующей страницы
curl https://api.mixmax.com/items?limit=2&sort=launchDate&next=2017-09-11T00%3A44%3A54.036Z_590e9abd4abbf1165862d342

const [nextLaunchDate, nextId] = req.query.next.split(‘_’);
const items = db.items.find({
  $or: [{
    launchDate: { $lt: nextLaunchDate }
  }, {
    // If the launchDate is an exact match, we need a tiebreaker, so we use the _id field from the cursor.
    launchDate: nextLaunchDate,
  _id: { $lt: nextId }
  }]
}).sort({
   _id: -1
}).limit(2);

const lastItem = items[items.length - 1];
// The cursor is a concatenation of the two cursor fields, since both are needed to satisfy the requirements of being a cursor field
const next = `${lastItem.launchDate}_${lastItem._id}`;
res.json({ items, next });

Ссылка: https://engineering.mixmax.com/blog/api-paging-built-the-right-way/

0 голосов
/ 04 октября 2019

Вы можете использовать опции skip и limit для разбиения на страницы

module.exports = (data)=>{

  let page = parseInt(data.page);
  let limit = parseInt(data.limit);
  let skip = 0

  if(page>1){
   skip = (page * limit);
   }


let mongoClient = require('mongodb').MongoClient;
    mongoClient.connect('mongodb://localhost:27017').then((client) => {
        let db = client.db('your-db');
        db.collection('your-collection').find({}, {limit:limit, skip:skip}).then((documents) => {
            console.log(documents);
        });

    });
};
0 голосов
/ 03 октября 2019

Я отправляю API, который находится на MongoDb и Nodejs.

module.exports.fetchLoans = function(req, res, next) {
    var perPage = 5;
    var page = req.body.page || 1;
    loans
      .find({ userId: req.user._id})
      .select("-emi")
      .skip(perPage * page - perPage)
      .limit(perPage)
      .sort({ timestamp: -1 })
      .exec(function(err, loan) {
        if (loan != null) {
          loans
            .find({ userId: req.user._id})
            .count()
            .exec(function(err, count) {
              if (count != null) {
                res.json({
                  success: true,
                  loans: loan,
                  currentpage: page,
                  totalpages: Math.ceil(count / perPage)
                });
              } else {
                console.log("Milestone Error: ", err);
                res.json({ success: false, error: "Internal Server Error. Please try again." });
              }
            });
        } else {
          console.log("Milestone Error: ", err);
          res.json({ success: false, error: "Internal Server Error. Please try again." });
        }
      });
  };

В этом коде вам нужно будет указывать номер страницы при каждом обращении.

...