MongoDB располагался в разбивке по страницам

Он сказал, что использование skip() для разбивки на страницы в коллекции MongoDB со многими записями медленное и не рекомендуется.

Можно использовать ранжированную разбивку на страницы (на основе сравнения > _id)

db.items.find({_id: {$gt: ObjectId('4f4a3ba2751e88780b000000')}});

Это хорошо для отображения prev. и следующие кнопки - но это не очень просто реализовать, когда вы хотите отображать фактические номера страниц 1... 5 6 7... 124 - вам нужно предварительно вычислить, с какой страницы "_id" начинается каждая страница.

У меня есть два вопроса:

1) Когда я должен начать беспокоиться об этом? Когда есть "слишком много записей" с заметным замедлением для skip()? 1 000? 1 000 000?

2) Каков наилучший способ показать ссылки с фактическими номерами страниц при использовании разбивки на страницы в диапазоне?

Ответ 1

Хороший вопрос!

"Сколько их слишком много?" - это, конечно, зависит от ваших данных и требований к производительности. Я лично чувствую себя некомфортно, когда пропускаю более 500-1000 записей.

Фактический ответ зависит от ваших требований. Вот что делают современные сайты (или, по крайней мере, некоторые из них).

Во-первых, navbar выглядит так:

1 2 3 ... 457

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

1 2 3 4 5 ... 457

Позвольте пропустить еще немного и перейдите на страницу 5.

1 ... 3 4 5 6 7 ... 457

Вы получаете идею. В каждой точке вы видите первую, последнюю и текущие страницы, а также две страницы вперед и назад от текущей страницы.

Запросы

var current_id; // id of first record on current page.

// go to page current+N
db.collection.find({_id: {$gte: current_id}}).
              skip(N * page_size).
              limit(page_size).
              sort({_id: 1});

// go to page current-N
// note that due to the nature of skipping back,
// this query will get you records in reverse order 
// (last records on the page being first in the resultset)
// You should reverse them in the app.
db.collection.find({_id: {$lt: current_id}}).
              skip((N-1)*page_size).
              limit(page_size).
              sort({_id: -1});

Ответ 2

Трудно дать общий ответ, потому что это зависит от того, какой запрос (или запросы) вы используете для построения набора результатов, которые отображаются. Если результаты могут быть найдены с использованием только индекса и представлены в порядке индекса, то db.dataset.find(). Limit(). Skip() может хорошо работать даже при большом количестве пропусков. Вероятно, это самый простой способ кодирования кода. Но даже в этом случае, если вы можете кэшировать номера страниц и связывать их с индексами, вы можете сделать это быстрее для второго и третьего лиц, которые хотят просмотреть страницу 71, например.

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