Några saker du kan göra här:
Först av allt, använd en $in istället för en $or.
För det andra kan MongoDB bara använd ett index för din första match, så du måste bestämma (genom att testa det) vilken av de två matchningarna som är bättre. Målet är att ha en så snabb fråga och så färre dokument som går igenom din pipeline. För det gör du följande saker:
Skapa först de tre indexen:
db.element.ensureIndex( { 'versions.branch' : 1 } );
db.element.ensureIndex( { 'doctype' : 1 } );
db.element.ensureIndex( { 'prefix' : 1 } );
Kör sedan följande tre frågor och lägg märke till fälten "markör", "n", "nScanned" och "ms":
branch = "nameofbranch"; // guessing here
db.element.find( "versions.branch": branch ).explain();
db.element.find( "doctype" { $in: [ "15281", "15282" .... ] } ).explain();
db.element.find( "prefix": { $ne: "500" } ).explain();
För den sista frågan kommer du att notera att "cursor" är "BasicCursor", eftersom en $ne-fråga inte kan använda indexet.
De andra två kommer att visa dig olika värden för "ms", "n" och "nScanned". "ms" är den tid det tog att köra frågan. Om detta är ungefär detsamma, titta på skillnaden mellan "n" och "nScanned" värden. Jag förväntar mig och gissar att skillnaden för "versions.branch"-frågan är 0. För "doctype"-frågan kan den vara annorlunda. Om "ms" inte är ungefär densamma sätter du $matchen som var snabbast först som $match-klausul i din aggregeringspipeline.
Om hastigheten ("ms") är samma, kontrollera "n"-värdena. Om "n" för "prefix"-frågan är säg "5" och "n" för "versions.branch"-frågan är "500" betyder det att resultatet av "prefix"-frågan är bättre, eftersom färre dokument returneras. I så fall lägger du in det som din första $match-klausul sammantaget. Om "versions.branch" är mycket mindre, använd den som första $match-klausul.