Hvis du ønsker den slags begrænsninger i forespørgslen, har du grundlæggende to muligheder afhængigt af, hvad din MongoDB-version understøtter:
MongoDB 3.6
Du vil helst bruge $expr
"udover" til alle normale forespørgselsbetingelser for faktisk at vælge gyldige dokumenter:
var A = 10, B = 40;
Model.find({
"subDocs.value": { "$all": [A, B] },
"$expr": {
"$lt": [
{ "$arrayElemAt": [
"$subDocs.index",
{ "$indexOfArray": [ "$subDocs.value", A ]}
]},
{ "$arrayElemAt": [
"$subDocs.index",
{ "$indexOfArray": [ "$subDocs.value", B ]}
]}
]
}
})
Eller matche det "sidste" forekomst:
Model.find({
"subDocs.value": { "$all": [A, B] },
"$expr": {
"$lt": [
{ "$arrayElemAt": [
"$subDocs.index",
{ "$subtract": [
{ "$subtract": [{ "$size": "$subDocs.value" }, 1 ] },
{ "$indexOfArray": [ { "$reverseArray": "$subDocs.value" }, A ] }
]}
]},
{ "$arrayElemAt": [
"$subDocs.index",
{ "$subtract": [
{ "$subtract": [{ "$size": "$subDocs.value" }, 1 ] },
{ "$indexOfArray": [ { "$reverseArray": "$subDocs.value" }, B ] }
]}
]}
]
}
})
Tidligere versioner
Det samme, men uden indbyggede operatører skal du bruge JavaScript-evalueringen af >$hvor
:
var A = 10, B = 40;
Model.find({
"subDocs.value": { "$all": [A, B] },
"$where": `this.subDocs.find( e => e.value === ${A}).index
< this.subDocs.find( e => e.value === ${B}).index`
})
Eller matche det "sidste" forekomst:
Model.find({
"subDocs.value": { "$all": [10,40] },
"$where": `let arr = this.subDocs.reverse();
return arr.find( e => e.value === ${A}).index
> arr.find( e => e.value === ${B}).index`
})
Hvis du havde brug for det i en aggregeringspipeline, ville du bruge $redact
og lignende logik til det første eksempel i stedet:
var A = 10, B = 40;
Model.aggregate([
{ "$match": { "subDocs.value": { "$all": [A, B] } } },
{ "$redact": {
"$cond": {
"if": {
"$lt": [
{ "$arrayElemAt": [
"$subDocs.index",
{ "$indexOfArray": [ "$subDocs.value", A ]}
]},
{ "$arrayElemAt": [
"$subDocs.index",
{ "$indexOfArray": [ "$subDocs.value", B ]}
]}
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Det er tilstrækkeligt at sige, at "sammenligningslogikken" faktisk ikke er hjemmehørende i "forespørgselsoperatorudtryk" selv, så den eneste del, der "optimalt" kan anvendes på et indeks, bruger $all
forespørgselsoperatør i alle tilfælde. Den væsentlige resterende logik gælder faktisk "efter" at hovedudtrykket er evalueret og "i tillæg til" for at der ikke returneres andre resultater end dem, der møder udtrykket med enten $expr
eller $where
.
Den grundlæggende logik for hver enkelt er i det væsentlige at udtrække værdien af "indeks"
egenskab fra det "første" array-medlem, der faktisk matcher den respektive værdi i "værdi"
ejendom. Hvor dette er "mindre end", så er betingelsen sand
og dette opfylder det dokument, der returneres.
Så bemærk, at enten "beregnet evaluering" matcher effektiviteten af forespørgselsoperatorer, og uden at blive brugt "i kombination" af andre forespørgselsoperatorbetingelser, som er i stand til at få adgang til et "indeks", vil en "fuld samlingsscanning" blive startet.
Men det overordnede resultat er bestemt mere effektivt end at returnere alle matchende elementer til den første forespørgselsbetingelse og derefter afvise dem på markøren "efter" returnering fra databasen.
Se også dokumentation for $arrayElemAt
, $indexOfArray
, $lt
og Array.find()
til JavaScript