MongoDB ranged pagination


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

ранжированная пагинация (на основе > _id comparsion) может быть использована

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

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

Так что у меня есть два вопросы:

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

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

2 65

2 ответа:

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

" сколько это слишком много?- это, конечно, зависит от размера ваших данных и требований к производительности. Лично я чувствую себя некомфортно, когда пропускаю более 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});

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

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