São muitas perguntas em um post;) Deixe-me analisá-las em uma ordem prática:
- Cada consulta pode usar no máximo um índice (com exceção das cláusulas $or de nível superior e outras). Isso inclui qualquer classificação.
- Devido ao exposto acima, você definitivamente precisará de um índice composto para o seu problema, em vez de índices separados por campo.
- Campos de baixa cardinalidade (ou seja, campos com poucos valores exclusivos em seu conjunto de dados) geralmente não devem estar no índice, pois sua seletividade é muito limitada.
- A ordem dos campos em seu índice composto é importante, assim como a direção relativa de cada campo em seu índice composto (por exemplo, "{name:1, age:-1}"). Há muita documentação sobre índices compostos e direções de campo de índice em mongodb.org, então não vou repetir tudo aqui.
- As classificações só usarão o índice se o campo de classificação estiver no índice e for o campo no índice logo após o último campo usado para selecionar o conjunto de resultados. Na maioria dos casos, esse seria o último campo do índice.
Portanto, você não deve incluir o status em seu índice, pois uma vez que a caminhada do índice eliminou a grande maioria dos documentos com base em campos de cardinalidade mais alta, ele terá no máximo 2-3 documentos restantes na maioria dos casos, o que dificilmente é otimizado por um índice de status (especialmente porque você mencionou que esses 2-3 documentos provavelmente terão o mesmo status de qualquer maneira).
Agora, a última observação relevante no seu caso é que, quando você usa consultas de intervalo (e você está), ele não usará o índice para classificação de qualquer maneira. Você pode verificar isso olhando para o valor "scanAndOrder" do seu explain() depois de testar sua consulta. Se esse valor existir e for verdadeiro, significa que ele classificará o conjunto de resultados na memória (varredura e ordem) em vez de usar o índice diretamente. Isso não pode ser evitado no seu caso específico.
Portanto, seu índice deve ser:
db.posts.ensureIndex({start:1, end:1})
e sua consulta (ordem modificada apenas para fins de clareza, o otimizador de consultas executará sua consulta original pelo mesmo caminho de execução, mas prefiro colocar os campos indexados primeiro e em ordem):
db.posts.find({start: {$lt: today}, end: {$gt: today}, status: {$gte:0}}).sort({sortOrder:1})