Cela fait beaucoup de questions en un seul post ;) Laissez-moi les passer en revue dans un ordre pratique :
- Chaque requête peut utiliser au plus un index (à l'exception des clauses $or de niveau supérieur et autres). Cela inclut tout tri.
- En raison de ce qui précède, vous aurez certainement besoin d'un index composé pour votre problème plutôt que d'index séparés par champ.
- Les champs à faible cardinalité (c'est-à-dire les champs avec très peu de valeurs uniques dans votre ensemble de données) ne doivent généralement pas figurer dans l'index, car leur sélectivité est très limitée.
- L'ordre des champs dans votre index composé est important, tout comme la direction relative de chaque champ dans votre index composé (par exemple, "{nom :1, âge :-1}"). Il y a beaucoup de documentation sur les index composés et les directions des champs d'index sur mongodb.org donc je ne vais pas tout répéter ici.
- Les tris n'utiliseront l'index que si le champ de tri est dans l'index et est le champ dans l'index directement après le dernier champ qui a été utilisé pour sélectionner le jeu de résultats. Dans la plupart des cas, il s'agirait du dernier champ de l'index.
Donc, vous ne devriez pas du tout inclure le statut dans votre index car une fois que la marche de l'index a éliminé la grande majorité des documents basés sur des champs de cardinalité plus élevée, il restera au plus 2-3 documents dans la plupart des cas, ce qui n'est guère optimisé par un index de statut (surtout depuis que vous avez mentionné que ces 2-3 documents ont de toute façon très probablement le même statut).
Maintenant, la dernière note pertinente dans votre cas est que lorsque vous utilisez des requêtes de plage (et vous l'êtes), l'index n'est de toute façon pas utilisé pour le tri. Vous pouvez vérifier cela en regardant la valeur "scanAndOrder" de votre expliquer () une fois que vous avez testé votre requête. Si cette valeur existe et est vraie, cela signifie qu'elle triera le jeu de résultats en mémoire (balayage et ordre) plutôt que d'utiliser l'index directement. Cela ne peut être évité dans votre cas spécifique.
Donc, votre index devrait donc être :
db.posts.ensureIndex({start:1, end:1})
et votre requête (ordre modifié uniquement pour plus de clarté, l'optimiseur de requête exécutera votre requête d'origine via le même chemin d'exécution mais je préfère mettre les champs indexés en premier et dans l'ordre) :
db.posts.find({start: {$lt: today}, end: {$gt: today}, status: {$gte:0}}).sort({sortOrder:1})