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