Przebieg może się na tym różnić i może się okazać, że „obecnie” proces, który realizujesz, jest przynajmniej „najbardziej dopasowany”. Ale prawdopodobnie możemy działać wydajniej.
Co możesz teraz zrobić
Pod warunkiem, że twoje tablice są już "posortowane" za pomocą $sortuj
modyfikator z $push
, prawdopodobnie możesz to zrobić:
db.somedb.find(
{
"partn.is_partner": true,
"$where": function() {
return this.partn.slice(-1)[0].is_partner == true;
}
},
{ "partn": { "$slice": -1 } }
)
Tak długo, jak partn,is_partner
jest „indeksowany”, jest to nadal dość wydajne, ponieważ początkowy warunek zapytania można spełnić za pomocą indeksu. Część, która nie może, to $where
tutaj klauzula, która używa oceny JavaScript.
Ale co ta druga część w $where
robi to po prostu "wycinanie" ostatniego elementu z tablicy i testowanie jego wartości is_partner
właściwość, aby sprawdzić, czy to prawda. Tylko wtedy, gdy ten warunek jest spełniony, dokument zostanie zwrócony.
Istnieje również $slice
operator projekcji. Robi to samo przy zwrocie ostatniego elementu z tablicy. Fałszywe dopasowania są już filtrowane, więc pokazuje tylko ostatni element, w którym jest prawdziwe.
W połączeniu z indeksem, jak wspomniano, powinno to być dość szybkie, biorąc pod uwagę, że dokumenty zostały już wybrane, a warunek JavaScript tylko filtruje resztę. Zauważ, że bez innego pola ze standardowym warunkiem zapytania do dopasowania, $where
klauzula nie może używać indeksu. Dlatego zawsze staraj się używać "oszczędnie" z innymi warunkami zapytania.
Co możesz zrobić w przyszłości
Następna w kolejce, chociaż nie jest dostępna w momencie pisania tego tekstu, ale na pewno w niedalekiej przyszłości będzie $slice
operator dla struktury agregacji. Jest to obecnie w branży deweloperskiej, ale oto, jak to działa:
db.somedb.aggregate([
{ "$match": { "partn.is_partner": true } },
{ "$redact": {
"$cond": {
"if": {
"$anyElementTrue": {
"$map": {
"input": { "$slice": ["$partn",-1] },
"as": "el",
"in": "$$el.is_partner"
}
}
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
{ "$project": {
"partn": { "$slice": [ "$partn",-1 ] }
}}
])
Łączenie tego $slice
w $redact
etap tutaj umożliwia filtrowanie dokumentów za pomocą warunku logicznego, testując dokument. W tym przypadku $slice
tworzy jednoelementową tablicę, która jest wysyłana do $ mapa
aby po prostu wyodrębnić pojedynczy is_partner
wartość (nadal jako tablica). Ponieważ w najlepszym przypadku jest to tablica jednoelementowa, drugi test to $anyElementTrue
co sprawia, że jest to pojedynczy wynik logiczny, odpowiedni dla $przewód
.
$redact
tutaj decyduje o tym wyniku, czy $$ZACHOWAJ
lub $$PRUNE
dokument z wyników. Później używamy $slice
ponownie w projekcie, aby po prostu zwrócić ostatni element tablicy po filtrowaniu.
Wygląda na to, że jest to dokładnie to samo, co robi wersja JavaScript, z wyjątkiem tego, że używa wszystkich natywnych operatorów kodowanych i dlatego powinno być nieco szybsze niż alternatywa JavaScript.
Oba formularze zwracają pierwszy dokument zgodnie z oczekiwaniami:
{
"_id" : 0,
"partn" : [
{
"date" : ISODate("2015-07-28T00:59:14.963Z"),
"is_partner" : true
},
{
"date" : ISODate("2015-07-28T01:00:32.771Z"),
"is_partner" : false
},
{
"date" : ISODate("2015-07-28T01:15:29.916Z"),
"is_partner" : true
},
{
"date" : ISODate("2015-08-05T13:48:07.035Z"),
"is_partner" : false
},
{
"date" : ISODate("2015-08-05T13:50:56.482Z"),
"is_partner" : true
}
]
}
Dużym haczykiem w obu przypadkach jest to, że twoja tablica musi być już posortowana, więc najnowsza data jest pierwsza. Bez tego potrzebujesz struktury agregacji do $sort
tablicę, tak jak teraz.
Niezbyt wydajne, dlatego powinieneś „wstępnie posortować” swoją tablicę i zachować porządek przy każdej aktualizacji.
Jako poręczna sztuczka, to faktycznie zmieni kolejność wszystkich elementów tablicy we wszystkich dokumentach kolekcji w jednej prostej instrukcji:
db.somedb.update(
{},
{ "$push": {
"partn": { "$each": [], "$sort": { "date": 1 } }
}},
{ "multi": true }
)
Więc nawet jeśli nie „wpychasz” nowego elementu do tablicy i tylko aktualizujesz właściwość, zawsze możesz zastosować tę podstawową konstrukcję, aby utrzymać porządek w tablicy, jak chcesz.
Warto rozważyć, ponieważ powinno to znacznie przyspieszyć.