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

Potok Agregacji MongoDB

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 pipeline jest 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.
                   ])