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