Dieses Kapitel führt eine detaillierte Erklärung der statistischen Analyse von MongoDB ein, die hauptsächlich über die Aggregation Pipeline erreicht wird. Sie ähnelt der "group by"-Anweisung in SQL. In der MongoDB-Shell wird die statistische Analyse mit der Funktion db.collection.aggregate() implementiert.

Voraussetzung Tutorial

MongoDB Aggregation Pipeline

Allgemeine Schritte

  • Verwenden von $match, um die Ziel-Daten zu filtern
  • Verwenden von $group, um die Daten zu gruppieren und zu berechnen
  • Verwenden von $sort, um die Ergebnisse zu sortieren (optional)

Testdaten

Die Daten in der orders-Sammlung sehen wie folgt aus

{ _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 }

aggregate-Funktion

db.collection.aggregate(pipeline) Erklärung:

  • Die pipeline nimmt einen Array-Parameter an, wobei jedes Element eine Verarbeitungsstufe darstellt.

Beispiel

db.orders.aggregate([
                     { $match: { status: "A" } },  // Erste Stufe
                     { $group: { _id: "$cust_id", total: { $sum: "$amount" } } },   // Zweite Stufe
                     { $sort: { total: -1 } }  // Dritte Stufe
                   ])

Äquivalentes SQL

select sum(amount) as total from orders 
        where status="A" 
        group by cust_id 
        order by total desc

$match-Stufe

Format:

{ $match: { <Abfrage> } }

Erklärung:

  • <Abfrage> MongoDB-Abfragebedingungen

Wird verwendet, um Abfragebedingungen festzulegen. Wenn $match ignoriert wird, impliziert dies die Abfrage aller Daten.

Tipp: Wenn Sie mit der MongoDB-Abfragesyntax nicht vertraut sind, lesen Sie bitte die vorherigen Kapitel.

$group-Stufe

Ähnlich wie die group by-Klausel in SQL wird sie verwendet, um die Daten zu gruppieren und dann eine Reihe statistischer Berechnungen an den gruppierten Daten durchzuführen.

Grundlegende Verwendung von $group

Syntax:

{
  $group:
    {
      _id: <Ausdruck>, // Gruppierungsbedingung, z.B.: nach welchem Feld gruppieren
      <Feld1>: { <Aggregator1> : <Ausdruck1> },  // Aggregationsoperation, Sie können N Aggregationsoperationen hinzufügen
      ...
    }
 }

Erklärung:

  • - Name des benutzerdefinierten statistischen Indikators, kann insgesamt N sein
  • - Aggregationsfunktion, ähnlich wie sum, avg und andere Aggregationsfunktionen in SQL, der Unterschied besteht darin, dass die Aggregationsfunktionen in MongoDB mit $ als Präfix benannt sind, z.B.: $sum, $avg
  • - Parameter der Aggregationsfunktion, normalerweise der zu zählende Feldwert, unter Verwendung des Formats "$Feldname" zur Referenzierung von Dokumentfeldern

Beispiel:

db.orders.aggregate([
                     {
					 	$group: { 
							_id: "$cust_id",
							total: { $sum: "$amount" }, // Der erste berechnete Indikator total, unter Verwendung des Summierungsoperators $sum
							amount_avg: {$avg: "$amount"}  // Der zweite berechnete Indikator avg, unter Verwendung des Durchschnittsberechnungsoperators $avg
						} 
					}
               ])

Ausgabe:

{ "_id" : "abc1", "total" : 75, "amount_avg" : 37,5 }
{ "_id" : "xyz1", "total" : 250, "amount_avg" : 83,33333333333333 }

Äquivalentes SQL:

select 
	sum(amount) as  total,
	avg(amount) as amount_avg
from orders 
group by cust_id

$group-Aggregationsfunktionen

Die üblicherweise verwendeten Aggregationsfunktionen für $group sind wie folgt:

Operator Beschreibung Beispiel
$avg Durchschnitt berechnen {$avg: "$amount"}
$sum Summe berechnen {$sum: "$amount"}
$max Maximalwert {$max: "$amount"}
$min Minimalwert {$min: "$amount"}
$first Nach Gruppierung Daten zurückgeben, den Inhalt des ersten Dokuments {$first: "$amount"}
$last Nach Gruppierung Daten zurückgeben, den Inhalt des letzten Dokuments {$last: "$amount"}
$push Nach Gruppierung Daten zurückgeben { $push: { ord_date: "$ord_date", amount: "$amount" }
$addToSet Nach Gruppierung Daten zurückgeben, anders als $push, da Duplikate entfernt werden { $addToSet: "$amount" }

Beispiel für $push

db.orders.aggregate(
   [
     {
       $group:
         {
           _id: "$cust_id",
           all: { $push: { ord_date: "$ord_date", amount: "$amount" } } // Werte der Felder ord_date und amount
         }
     }
   ]
)

Ausgabe

{ "_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 } ] }

Beispiel für $addToSet

db.orders.aggregate(
   [
     {
       $group:
         {
           _id: "$cust_id",
           all_amount: { $addToSet: "$amount" } // Gibt alle verschiedenen Betragswerte zurück
         }
     }
   ]
)

Ausgabe

{ "_id" : "abc1", "all_amount" : [ 25, 50 ] }
{ "_id" : "xyz1", "all_amount" : [ 100, 25, 125 ] }

$sort:

Die $sort-Phase wird typischerweise am Ende platziert, um die aggregierten Daten zu sortieren.

Format:

{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }

Erklärung:

  • , - Die Namen der zu sortierenden Felder, unterstützt mehrere Felder.
  • - Die Sortierrichtung, -1 für absteigend, 1 für aufsteigend.

Beispiel:

db.orders.aggregate([
                     { $match: { status: "A" } },
                     { $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
                     { $sort: { total: -1 } }
                   ])

Aggregat-Paginierung

Wir können die Paginierung mithilfe der $limit- und $skip-Operatoren implementieren.

Beispiel:

db.orders.aggregate([
                     { $match: { status: "A" } },
                     { $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
                     { $sort: { total: -1 } },
					 { $limit: 5 }, // Begrenzt die Anzahl der zurückgegebenen Datensätze, ähnlich wie die Seitengröße bei der Paginierung.
					 { $skip: 1 } // Überspringt eine bestimmte Anzahl von Datensätzen, ähnlich wie der Offset in SQL.
                   ])