Pokud chcete v dotazu takové omezení, pak máte v podstatě dvě možnosti v závislosti na tom, co vaše verze MongoDB podporuje:
MongoDB 3.6
Nejlépe byste použili $expr
"navíc" na jakékoli normální podmínky dotazu, abyste skutečně vybrali platné dokumenty:
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 ]}
]}
]
}
})
Nebo odpovídající "poslední" výskyt:
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 ] }
]}
]}
]
}
})
Starší verze
Totéž, ale bez nativních operátorů musíte použít JavaScript hodnocení $ kde
:
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`
})
Nebo odpovídající "poslední" výskyt:
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`
})
Pokud byste to potřebovali v agregačním kanálu, pak byste použili $redact
a podobná logika jako v prvním příkladu:
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"
}
}}
])
Stačí říci, že „logika porovnání“ není ve skutečnosti nativní pro samotné „výrazy operátorů dotazu“, takže jediná část, která „optimálně“ lze použít na index pomocí $all
operátor dotazu ve všech případech. Základní zbývající logika ve skutečnosti platí „po“ vyhodnocení hlavního výrazu a „navíc“, aby nebyly vráceny žádné jiné výsledky než ty, které splňují výraz buď s $expr
nebo $where
.
Základní logikou každého z nich je v podstatě extrahovat hodnotu "index"
vlastnost z "prvního" člena pole, která skutečně odpovídá příslušné hodnotě v "value"
vlastnictví. Kde je toto "menší než", pak je podmínka true
a to vyhovuje vracenému dokumentu.
Všimněte si tedy, že buď „vypočítané vyhodnocení“ odpovídá efektivitě operátorů dotazu, a bez použití „v kombinaci“ s jinými podmínkami operátora dotazu, které mají přístup k „indexu“, bude zahájeno „skenování celé kolekce“.
Ale celkový výsledek je určitě efektivnější než vracet všechny odpovídající položky do první podmínky dotazu a pak je odmítat na kurzoru "po" návratu z databáze.
Viz také dokumentaci pro $arrayElemAt
, $indexOfArray
, $lt
a Array.find()
pro JavaScript