Jak korzystać z potoku agregacji w MongoDB

Potok Agregacji w MongoDB: Efektywne Przetwarzanie Danych

W MongoDB, do realizacji skomplikowanych zapytań, zaleca się stosowanie potoku agregacji. Jeśli dotychczas używałeś MapReduce, warto rozważyć przejście na potok agregacji, który zapewnia bardziej efektywne przetwarzanie.

Czym Jest Agregacja w MongoDB i Jak Działa?

Potok agregacji to wieloetapowy mechanizm służący do wykonywania złożonych zapytań w MongoDB. Działa poprzez szereg etapów, zwanych potokiem. Rezultaty wygenerowane w jednym etapie mogą stanowić podstawę dla operacji w kolejnym.

Przykładowo, wynik operacji filtrowania ($match) można przekazać do etapu sortowania, i tak dalej, aż uzyskamy pożądany rezultat.

Każdy etap potoku wykorzystuje operator MongoDB i generuje jeden lub więcej zmodyfikowanych dokumentów. W zależności od zapytania, dany etap może pojawić się w potoku wielokrotnie. Na przykład, operatory takie jak $count lub $sort mogą być użyte kilka razy w ramach jednego potoku agregacji.

Etapy Potoku Agregacji

Potok agregacji przekształca dane, przechodząc przez różne etapy w ramach jednego zapytania. Dostępnych jest kilka etapów, a ich szczegółowy opis znajduje się w dokumentacji MongoDB.

Poniżej omówimy niektóre z najczęściej stosowanych etapów:

Etap $match

Etap $match pozwala na zdefiniowanie warunków filtracji na początku procesu agregacji. Umożliwia wybór danych, które będą brane pod uwagę w dalszych etapach potoku.

Etap $group

Etap $group dzieli dane na grupy w oparciu o określone kryteria, wykorzystując pary klucz-wartość. Każda grupa jest reprezentowana przez klucz w dokumencie wyjściowym.

Rozważmy przykładowe dane sprzedażowe:

Używając potoku agregacji, możemy obliczyć całkowitą liczbę sprzedanych produktów i największą sprzedaż dla każdej kategorii:

 {
$group: {
_id: $Section,
total_sales_count: {$sum : $Sold},
top_sales: {$max: $Amount},
}
}

Para `_id: $Section` grupuje wyniki na podstawie sekcji. Określając pola `total_sales_count` i `top_sales`, MongoDB tworzy nowe klucze w oparciu o agregatory, takie jak suma (`$sum`), minimum (`$min`), maksimum (`$max`) lub średnia (`$avg`).

Etap $skip

Etap $skip umożliwia pominięcie określonej liczby dokumentów w wynikach. Najczęściej używany jest po etapie grupowania. Na przykład, jeśli spodziewamy się dwóch dokumentów, ale pominiemy jeden, agregacja zwróci tylko drugi dokument.

Aby dodać etap pominięcia, wstaw operację $skip do potoku:

 ...,
{
$skip: 1
},

Etap $sort

Etap $sort umożliwia uporządkowanie danych w porządku rosnącym lub malejącym. Na przykład, możemy posortować dane z poprzedniego przykładu w kolejności malejącej, aby zobaczyć, która sekcja ma największą sprzedaż.

Dodajmy operator $sort do wcześniejszego zapytania:

 ...,
{
$sort: {top_sales: -1}
},

Etap $limit

Operacja $limit ogranicza liczbę dokumentów wyjściowych w potoku agregacji. Na przykład, użyjemy operatora $limit, aby uzyskać sekcję o najwyższej sprzedaży, która została zwrócona w poprzednim kroku:

 ...,
{
$sort: {top_sales: -1}
},

{"$limit": 1}

Powyższe zwróci tylko pierwszy dokument, czyli sekcję z najwyższą sprzedażą.

Etap $project

Etap $project pozwala na dostosowanie struktury dokumentu wyjściowego. Używając operatora $project, możemy określić, które pola mają zostać uwzględnione w wynikach, a także zmienić ich nazwy.

Przykładowy wynik bez etapu $project wygląda następująco:

Zobaczmy jak to wygląda po zastosowaniu etapu $project. Aby dodać projekt $ do potoku:

 ...,

{
"$project": {
"_id": 0,
"Section": "$_id",
"TotalSold": "$total_sales_count",
"TopSale": "$top_sales",

}
}

Ponieważ wcześniej zgrupowaliśmy dane według sekcji produktów, powyższe zachowuje każdą sekcję w wynikach. Dodatkowo, zmienia nazwy zagregowanych wartości na `TotalSold` i `TopSale`, co poprawia czytelność.

Finalny wynik jest znacznie bardziej przejrzysty:

Etap $unwind

Etap $unwind rozdziela tablicę w dokumencie na pojedyncze dokumenty. Weźmy na przykład dane dotyczące zamówień:

Użyjemy etapu $unwind, aby rozbić tablicę `items`, co ułatwi dalszą agregację. Rozwijanie tablicy `items` ma sens, jeśli chcemy obliczyć całkowity przychód dla każdego produktu:

 db.Orders.aggregate(
[
{
"$unwind": "$items"
},
{
"$group": {
"_id": "$items.product",
"total_revenue": { "$sum": { "$multiply": ["$items.quantity", "$items.price"] } }
}
},
{
"$sort": { "total_revenue": -1 }
},

{
"$project": {
"_id": 0,
"Product": "$_id",
"TotalRevenue": "$total_revenue",

}
}
])

Oto wynik powyższego zapytania:

Jak Utworzyć Potok Agregacji w MongoDB

Potok agregacji może zawierać wiele operacji. Przedstawione wcześniej etapy i przykłady pokazują, jak z nich korzystać, łącznie z podstawowymi zapytaniami dla każdego z nich.

Korzystając z poprzednich danych sprzedażowych, połączymy kilka etapów, aby pokazać, jak działa cały potok agregacji:

 db.sales.aggregate([

{
"$match": {
"Sold": { "$gte": 5 }
}
},

{

"$group": {
"_id": "$Section",
"total_sales_count": { "$sum": "$Sold" },
"top_sales": { "$max": "$Amount" },

}

},

{
"$sort": { "top_sales": -1 }
},

{"$skip": 0},

{
"$project": {
"_id": 0,
"Section": "$_id",
"TotalSold": "$total_sales_count",
"TopSale": "$top_sales",

}
}

])

Ostateczny wynik jest podobny do tego, co widzieliśmy wcześniej:

Potok Agregacji vs MapReduce

Przed wprowadzeniem potoku agregacji, MapReduce było tradycyjnym sposobem agregowania danych w MongoDB. MapReduce ma zastosowanie nie tylko w MongoDB, ale jest mniej wydajne niż potok agregacji i wymaga użycia oddzielnego skryptu do mapowania i redukcji danych.

Potok agregacji jest specyficzny dla MongoDB i zapewnia wydajniejsze i łatwiejsze podejście do złożonych zapytań. Oprócz prostoty i skalowalności zapytań, poszczególne etapy potoku dają większą kontrolę nad formą danych wyjściowych.

Istnieje wiele różnic między potokiem agregacji a MapReduce. Zauważysz je, gdy przejdziesz z MapReduce na potok agregacji.

Efektywne Zapytania Big Data w MongoDB

Aby przeprowadzić zaawansowane obliczenia na złożonych danych w MongoDB, zapytanie musi być jak najbardziej efektywne. Potok agregacji jest idealny do takich zadań. Zamiast manipulować danymi w osobnych operacjach, co obniża wydajność, agregacja pozwala na zebranie ich w jednym wydajnym potoku i wykonanie ich naraz.

Chociaż potok agregacji jest wydajniejszy niż MapReduce, możemy dodatkowo zwiększyć wydajność, indeksując dane. Ograniczy to ilość danych, które MongoDB musi skanować na każdym etapie agregacji.


newsblog.pl