Ten rozdział przedstawia szczegółowe wyjaśnienie analizy statystycznej w MongoDB, głównie osiągniętej za pomocą potoku agregacji. Jest podobny do instrukcji "group by" w SQL. W powłoce MongoDB, analiza statystyczna jest realizowana za pomocą funkcji db.collection.aggregate().
Samouczek wstępny
Ogólne kroki
- Użyj $match, aby filtrować docelowe dane
- Użyj $group, aby zgrupować i obliczyć dane
- Użyj $sort, aby opcjonalnie posortować wyniki
Dane testowe
Dane w kolekcji orders wyglądają następująco
{ _id: 1, cust_id: "abc1", ord_date: ISODate("2012-11-02T17:04:11.102Z"), status: "A", amount: 50 }
{ _id: 2, cust_id: "xyz1", ord_date: ISODate("2013-10-01T17:04:11.102Z"), status: "A", amount: 100 }
{ _id: 3, cust_id: "xyz1", ord_date: ISODate("2013-10-12T17:04:11.102Z"), status: "D", amount: 25 }
{ _id: 4, cust_id: "xyz1", ord_date: ISODate("2013-10-11T17:04:11.102Z"), status: "D", amount: 125 }
{ _id: 5, cust_id: "abc1", ord_date: ISODate("2013-11-12T17:04:11.102Z"), status: "A", amount: 25 }
Funkcja agregacji
db.collection.aggregate(pipeline)
Wyjaśnienie:
- Parametrem pipelinejest tablica, gdzie każdy element reprezentuje etap przetwarzania.
Przykład
db.orders.aggregate([
                     { $match: { status: "A" } },  // Pierwszy etap
                     { $group: { _id: "$cust_id", total: { $sum: "$amount" } } },   // Drugi etap
                     { $sort: { total: -1 } }  // Trzeci etap
                   ])
Odpowiednik w SQL
select sum(amount) as total from orders 
        where status="A" 
        group by cust_id 
        order by total desc
Etap $match
Format:
{ $match: { <query> } }
Wyjaśnienie:
- 
<query>Warunki zapytania MongoDB
Służy do ustawiania warunków zapytania. Jeśli pominięto $match, oznacza to zapytywanie wszystkich danych.
Wskazówka: Jeśli nie jesteś zaznajomiony z składnią zapytania MongoDB, prosimy o odwołanie się do poprzednich rozdziałów.
Etap $group
Podobnie jak klauzula group by w SQL, służy do grupowania danych, a następnie wykonywania serii obliczeń statystycznych na zgrupowanych danych.
Podstawowe użycie $group
Składnia:
{
  $group:
    {
      _id: <expression>, // Warunek grupowania, na przykład: grupuj według którego pola
      <field1>: { <akumulator1> : <expression1> },  // Operacja agregacji, można dodać N operacji agregacji
      ...
    }
 }
Wyjaśnienie:
- 
- Nazwa niestandardowego wskaźnika statystycznego, może ich być N w sumie 
- 
- Funkcja agregacji, podobna do sumy SQL, średniej i innych funkcji agregacji, różnica polega na tym, że funkcje agregacji MongoDB są nazwane z prefiksem $, na przykład: $sum, $avg 
- 
- Parametr funkcji agregacji, zazwyczaj wartość pola do zliczania, odwołując się do pól dokumentu za pomocą formatu "$nazwa pola" 
Przykład:
db.orders.aggregate([
                     {
					 	$group: { 
							_id: "$cust_id",
							total: { $sum: "$amount" }, // Dodaj pierwszy wyliczony wskaźnik total, używając operatora sumy $sum
							amount_avg: {$avg: "$amount"}  // Dodaj drugi wyliczony wskaźnik avg, używając operatora obliczania średniej $avg
						 } 
					}
               ])
Wynik:
{ "_id" : "abc1", "total" : 75, "amount_avg" : 37.5 }
{ "_id" : "xyz1", "total" : 250, "amount_avg" : 83.33333333333333 }
Odpowiednik w SQL:
select 
	sum(amount) as  total,
	avg(amount) as amount_avg
from orders 
group by cust_id
Funkcje agregacji $group
Powszechnie używane funkcje agregacji dla $group to:
| Operator | Opis | Przykład | 
|---|---|---|
| $avg | Oblicz średnią | {$avg: "$amount"} | 
| $sum | Suma | {$sum: "$amount"} | 
| $max | Wartość maksymalna | {$max: "$amount"} | 
| $min | Wartość minimalna | {$min: "$amount"} | 
| $first | Zwraca dane po grupowaniu, zawartość pierwszego dokumentu | {$first: "$amount"} | 
| $last | Zwraca dane po grupowaniu, zawartość ostatniego dokumentu | {$last: "$amount"} | 
| $push | Zwraca dane po grupowaniu | { $push: { ord_date: "$ord_date", amount: "$amount" } | 
| $addToSet | Zwraca dane po grupowaniu, różni się od $push, ponieważ usuwa duplikaty | { $addToSet: "$amount" } | 
Przykład użycia $push
db.orders.aggregate(
   [
     {
       $group:
         {
           _id: "$cust_id",
           all: { $push: { ord_date: "$ord_date", amount: "$amount" } } // Wartości pól ord_date i amount
         }
     }
   ]
)
Output
{ "_id" : "abc1", "all" : [ { "ord_date" : "2021-04-18 00:00:00", "amount" : 50 }, { "ord_date" : "2021-04-21 00:00:00", "amount" : 25 } ] }
{ "_id" : "xyz1", "all" : [ { "ord_date" : "2021-04-18 00:00:00", "amount" : 100 }, { "ord_date" : "2021-04-20 00:00:00", "amount" : 25 }, { "ord_date" : "2021-04-21 00:00:00", "amount" : 125 } ] }
Przykład użycia $addToSet
db.orders.aggregate(
   [
     {
       $group:
         {
           _id: "$cust_id",
           all_amount: { $addToSet: "$amount" } // Zwraca wszystkie unikalne wartości amount
         }
     }
   ]
)
Output
{ "_id" : "abc1", "all_amount" : [ 25, 50 ] }
{ "_id" : "xyz1", "all_amount" : [ 100, 25, 125 ] }
$sort:
Etap $sort jest zazwyczaj umieszczany na końcu, aby posortować zagregowane dane.
Format:
{ $sort: { <pole1>: <kolejność sortowania>, <pole2>: <kolejność sortowania> ... } }
Wyjaśnienie:
- 
, - Nazwy pól do posortowania, obsługuje wiele pól. 
- <kolejność sortowania> - Kierunek sortowania, -1 dla malejącego, 1 dla rosnącego.
Przykład:
db.orders.aggregate([
                     { $match: { status: "A" } },
                     { $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
                     { $sort: { total: -1 } }
                   ])
Paginacja agregacji
Możemy zaimplementować paginację przy użyciu operatorów $limit i $skip.
Przykład:
db.orders.aggregate([
                     { $match: { status: "A" } },
                     { $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
                     { $sort: { total: -1 } },
					 { $limit: 5 }, // Ogranicza liczbę zwróconych rekordów, podobnie jak rozmiar strony w paginacji.
					 { $skip: 1 } // Pomija określoną liczbę rekordów, podobnie jak offset w SQL.
                   ])