Det är många frågor i ett inlägg;) Låt mig gå igenom dem i praktisk ordning :
- Varje fråga kan använda högst ett index (med undantag för $eller satser på toppnivå och sådant). Detta inkluderar all sortering.
- På grund av ovanstående kommer du definitivt att behöva ett sammansatt index för ditt problem snarare än separata index per fält.
- Fält med låg kardinalitet (alltså fält med väldigt få unika värden i din datauppsättning) bör vanligtvis inte finnas i indexet eftersom deras selektivitet är mycket begränsad.
- Fältens ordningsföljd i ditt sammansatta index spelar roll, och det har också den relativa riktningen för varje fält i ditt sammansatta index (t.ex. "{namn:1, ålder:-1}"). Det finns mycket dokumentation om sammansatta index och indexfältsanvisningar på mongodb.org så jag kommer inte att upprepa allt här.
- Sortering kommer bara att använda indexet om sorteringsfältet finns i indexet och är fältet i indexet direkt efter det senaste fältet som användes för att välja resultatuppsättningen. I de flesta fall skulle detta vara det sista fältet i indexet.
Så du bör inte inkludera status i ditt index alls eftersom när indexvandringen har eliminerat de allra flesta dokument baserade på högre kardinalitetsfält kommer det som mest att ha 2-3 dokument kvar i de flesta fall, vilket knappast optimeras av ett statusindex (speciellt eftersom du nämnde att dessa 2-3 dokument är mycket sannolikt att ha samma status ändå).
Nu, den sista anmärkningen som är relevant i ditt fall är att när du använder intervallfrågor (och det gör du) kommer den inte att använda indexet för sortering ändå. Du kan kontrollera detta genom att titta på "scanAndOrder"-värdet för din explain() när du har testat din fråga. Om det värdet finns och är sant betyder det att det kommer att sortera resultatuppsättningen i minnet (skanna och ordna) istället för att använda indexet direkt. Detta kan inte undvikas i ditt specifika fall.
Så ditt index bör därför vara :
db.posts.ensureIndex({start:1, end:1})
och din fråga (endast modifierad ordning för tydlighetens skull, frågeoptimeraren kör din ursprungliga fråga genom samma körväg men jag föredrar att placera indexerade fält först och i ordning) :
db.posts.find({start: {$lt: today}, end: {$gt: today}, status: {$gte:0}}).sort({sortOrder:1})