La pagination à distance de MongoDB

Il est dit que l’utilisation de skip () pour la pagination dans la collection MongoDB avec de nombreux enregistrements est lente et déconseillée.

La pagination à distance (basée sur> _id comparsion) pourrait être utilisée

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

C’est bon pour afficher prev. & boutons suivants – mais il n’est pas très facile à mettre en œuvre lorsque vous souhaitez afficher les numéros de page 1 … 5 6 7 … 124 – vous devez calculer à l’avance à partir de “_id” le début de chaque page.

J’ai donc deux questions:

1) Quand devrais-je commencer à m’inquiéter à ce sujet? Quand il y a “trop ​​de disques” avec un ralentissement notable pour skip ()? 1 000? 1 000 000?

2) Quelle est la meilleure approche pour montrer les liens avec les numéros de page réels en utilisant la pagination à distance?

Bonne question!

“Combien sont trop nombreux?” – cela dépend bien sûr de la taille de vos données et de vos exigences de performances. Personnellement, je me sens mal à l’aise quand je saute plus de 500 à 1000 enregistrements.

La réponse dépend de vos besoins. Voici ce que font les sites modernes (ou du moins certains d’entre eux).

Tout d’abord, la barre de navigation ressemble à ceci:

 1 2 3 ... 457 

Ils obtiennent le numéro de page final du nombre total d’enregistrements et du format de page. Passons à la page 3. Cela impliquera de sauter du premier enregistrement. Lorsque les résultats arrivent, vous connaissez l’identifiant du premier enregistrement à la page 3.

 1 2 3 4 5 ... 457 

Sautons un peu plus et allons à la page 5.

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

Vous avez eu l’idée. À chaque point, vous voyez les premières pages, les dernières et les dernières pages, ainsi que deux pages avant et arrière de la page actuelle.

Requêtes

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

Il est difficile de donner une réponse générale car cela dépend beaucoup de la requête (ou des requêtes) que vous utilisez pour construire l’ensemble des résultats affichés. Si les résultats peuvent être trouvés uniquement à l’aide de l’index et sont présentés dans l’ordre d’index, alors db.dataset.find (). Limit (). Skip () peut être performant même avec un grand nombre de sauts. C’est probablement l’approche la plus simple pour coder. Mais même dans ce cas, si vous pouvez mettre en cache des numéros de page et les lier à des valeurs d’index, vous pouvez les rendre plus rapides pour la deuxième et la troisième personne qui souhaitent afficher la page 71, par exemple.

Dans un jeu de données très dynamic où des documents seront ajoutés et supprimés alors que quelqu’un d’autre parcourt les données, cette mise en cache sera rapidement obsolète et la méthode des limites et des sauts sera peut-être la seule assez fiable pour donner de bons résultats.