Jeśli chcesz tego rodzaju ograniczenia w zapytaniu, masz zasadniczo dwie opcje, w zależności od tego, co obsługuje Twoja wersja MongoDB:
MongoDB 3.6
Najlepiej użyć $expr
„dodatkowo” do dowolnych normalnych warunków zapytania, aby wybrać prawidłowe 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 ]}
]}
]
}
})
Lub pasujące do „ostatniego” wystąpienie:
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 ] }
]}
]}
]
}
})
Wcześniejsze wersje
To samo, ale bez natywnych operatorów musisz użyć oceny JavaScript $gdzie
:
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`
})
Lub pasujące do „ostatniego” wystąpienie:
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`
})
Jeśli potrzebujesz tego w potoku agregacji, użyjesz $redaguj
i podobna logika do pierwszego przykładu:
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"
}
}}
])
Wystarczy powiedzieć, że „logika porównania” nie jest w rzeczywistości natywna dla samych „wyrażeń operatora zapytania”, więc jest to jedyna część, która „optymalnie” można zastosować do indeksu przy użyciu $all
operator zapytania we wszystkich przypadkach. Podstawowa pozostała logika faktycznie ma zastosowanie „po” tym, że główne wyrażenie jest oceniane i „dodatkowo do”, aby żadne wyniki nie zostały zwrócone poza tymi, które spełniają wyrażenie z $expr
lub $where
.
Podstawową logiką każdego z nich jest wyodrębnienie wartości "indeksu"
właściwość z "pierwszego" elementu tablicy, który faktycznie pasuje do odpowiedniej wartości w "value"
własność. Jeżeli jest to „mniejsze niż”, wtedy warunek jest prawda
a to odpowiada zwracanemu dokumentowi.
Zwróć więc uwagę, że albo „obliczona ocena” odpowiada wydajności operatorów zapytań i bez użycia „w połączeniu” innych warunków operatora zapytań, które są w stanie uzyskać dostęp do „indeksu”, zostanie zainicjowane „pełne skanowanie kolekcji”.
Ale ogólny wynik jest z pewnością bardziej wydajny niż zwracanie wszystkich pasujących elementów do pierwszego warunku zapytania, a następnie odrzucanie ich na kursorze „po” powrocie z bazy danych.
Zobacz także dokumentację $arrayElemAt
, $indexOfArray
, $lt
i Array.find()
dla JavaScript