Musisz użyć struktury agregacji. Agregacja będzie wyglądać mniej więcej tak:
db.stack.aggregate([
{ $match: { "samples.key" : "test-key" } },
{ $unwind : "$samples" },
{ $match : { "samples.key" : "test-key" } },
{ $project : { "new_key" : "$samples.key", "new_value" : "$samples.value" } },
{ $group : { `_id` : "$new_key", answer : { $avg : "$new_value" } } }
])
Najlepszym sposobem myślenia o ramach agregacji jest jak linia montażowa. Samo zapytanie jest tablicą dokumentów JSON, gdzie każdy dokument podrzędny reprezentuje inny krok w zespole.
Krok 1:$dopasuj
Pierwszym krokiem jest podstawowy filtr, taki jak klauzula WHERE w SQL. Umieszczamy ten krok jako pierwszy, aby odfiltrować wszystkie dokumenty, które nie zawierają elementu tablicy zawierającego test-key
. Umieszczenie tego na początku potoku umożliwia agregacji korzystanie z indeksów.
Krok 2:$odpręż się
Drugi krok, $unwind
, służy do oddzielenia każdego z elementów w tablicy „samples”, dzięki czemu możemy wykonywać operacje na nich wszystkich. Jeśli uruchomisz zapytanie tylko w tym kroku, zobaczysz, o co mi chodzi.Krótka historia:
{ name : "bob",
children : [ {"name" : mary}, { "name" : "sue" } ]
}
staje się dwoma dokumentami:
{ name : "bob", children : [ { "name" : mary } ] }
{ name : "bob", children : [ { "name" : sue } ] }
Krok 3:$dopasuj
Trzeci krok, $match
, jest dokładnym duplikatem pierwszego $match
etap, ale ma inny cel. Ponieważ następuje po $unwind
, ten etap odfiltrowuje poprzednie elementy tablicy, teraz dokumenty, które nie spełniają kryteriów filtrowania. W takim przypadku przechowujemy tylko dokumenty, w których samples.key = "test-key"
Krok 4:$projekt (opcjonalnie)
Czwarty krok, $project
, restrukturyzuje dokument. W tym przypadku wyciągnąłem elementy z tablicy, aby móc się do nich bezpośrednio odwoływać. Korzystając z powyższego przykładu.
{ name : "bob", children : [ { "name" : mary } ] }
staje się
{ new_name : "bob", new_child_name : mary }
Zauważ, że ten krok jest całkowicie opcjonalny; późniejsze etapy mogą zostać ukończone nawet bez tego $project
po kilku drobnych zmianach. W większości przypadków $project
jest całkowicie kosmetyczny; agregacje mają pod maską liczne optymalizacje, takie jak ręczne włączanie lub wykluczanie pól w $project
nie powinno być konieczne.
Krok 5:$grupa
Wreszcie $group
to miejsce, w którym dzieje się magia. _id
doceniaj to, według czego będziesz „grupować” w świecie SQL. Drugie pole mówi o uśrednieniu wartości zdefiniowanej w $project
krok. Możesz łatwo zastąpić $sum
wykonać sumę, ale operacja liczenia jest zwykle wykonywana w następujący sposób:my_count : { $sum : 1 }
.
Najważniejszą rzeczą, na którą należy zwrócić uwagę, jest to, że większość wykonywanej pracy polega na sformatowaniu danych do punktu, w którym wykonanie operacji jest proste.
Uwaga końcowa
Na koniec chciałem zauważyć, że to nie pracuj na przykładowych danych dostarczonych od samples.value
jest zdefiniowany jako tekst, którego nie można używać w operacjach arytmetycznych. Jeśli jesteś zainteresowany, zmiana typu pola jest opisana tutaj:MongoDB Jak zmienić typ pola