Ci sono molte domande in un post;) Lascia che le esamini in un ordine pratico :
- Ogni query può utilizzare al massimo un indice (ad eccezione di $ o clausole di livello superiore e simili). Ciò include qualsiasi ordinamento.
- A causa di quanto sopra, avrai sicuramente bisogno di un indice composto per il tuo problema piuttosto che di indici separati per campo.
- I campi a cardinalità bassa (quindi campi con pochissimi valori univoci nel set di dati) di solito non dovrebbero essere nell'indice poiché la loro selettività è molto limitata.
- L'ordine dei campi nel tuo indice composto è importante, così come la direzione relativa di ciascun campo nel tuo indice composto (ad es. "{nome:1, età:-1}"). C'è molta documentazione sugli indici composti e le indicazioni sui campi degli indici su mongodb.org, quindi non la ripeterò tutta qui.
- Gli ordinamenti utilizzeranno l'indice solo se il campo di ordinamento è nell'indice ed è il campo nell'indice subito dopo l'ultimo campo utilizzato per selezionare il set di risultati. Nella maggior parte dei casi questo sarebbe l'ultimo campo dell'indice.
Quindi, non dovresti includere lo stato nel tuo indice poiché una volta che l'indice walk ha eliminato la stragrande maggioranza dei documenti basati su campi a cardinalità più alta, nella maggior parte dei casi saranno rimasti al massimo 2-3 documenti, il che è difficilmente ottimizzato da un indice di stato (soprattutto perché hai menzionato che è molto probabile che quei 2-3 documenti abbiano comunque lo stesso stato).
Ora, l'ultima nota rilevante nel tuo caso è che quando usi le query di intervallo (e lo sei) non utilizzerà comunque l'indice per l'ordinamento. Puoi verificarlo osservando il valore "scanAndOrder" del tuo spiegare() dopo aver testato la tua query. Se quel valore esiste ed è vero significa che ordinerà il set di risultati in memoria (scansione e ordine) anziché utilizzare direttamente l'indice. Questo non può essere evitato nel tuo caso specifico.
Quindi, il tuo indice dovrebbe quindi essere :
db.posts.ensureIndex({start:1, end:1})
e la tua query (ordine modificato solo per chiarezza, Query Optimizer eseguirà la tua query originale attraverso lo stesso percorso di esecuzione ma preferisco mettere i campi indicizzati prima e in ordine):
db.posts.find({start: {$lt: today}, end: {$gt: today}, status: {$gte:0}}).sort({sortOrder:1})