J'ai trouvé plus performant de combiner les deux concepts ensemble (à la fois un skip+limit et un find+limit). Le problème avec skip+limit est la mauvaise performance lorsque vous avez beaucoup de documents (en particulier les plus grands documents). Le problème avec find+limit est que vous ne pouvez pas sauter à une page arbitraire. Je veux être capable de paginer sans le faire séquentiellement.
Les mesures que je prends sont :
- Créez un index basé sur la façon dont vous voulez trier vos documents, ou utilisez simplement l'index _id par défaut (c'est ce que j'ai utilisé).
- Connaître la valeur de départ, la taille de la page et la page à laquelle vous voulez accéder.
- Projet + saut + limite la valeur à partir de laquelle vous devriez commencer
- Rechercher + limiter les résultats de la page
Cela ressemble à peu près à ceci si je veux obtenir la page 5432 de 16 enregistrements (en javascript) :
let page = 5432;
let page_size = 16;
let skip_size = page * page_size;
let retval = await db.collection(...).find().sort({ "_id": 1 }).project({ "_id": 1 }).skip(skip_size).limit(1).toArray();
let start_id = retval[0].id;
retval = await db.collection(...).find({ "_id": { "$gte": new mongo.ObjectID(start_id) } }).sort({ "_id": 1 }).project(...).limit(page_size).toArray();
Cela fonctionne parce qu'un saut sur un index projeté est très rapide même si vous sautez des millions d'enregistrements (ce que je fais). si vous exécutez explain("executionStats")
mais il reste un grand nombre de personnes pour totalDocsExamined
mais en raison de la projection sur un index, elle est extrêmement rapide (essentiellement, les blocs de données ne sont jamais examinés). Ensuite, avec la valeur du début de la page en main, vous pouvez aller chercher la page suivante très rapidement.