Suche…


Einführung

Aggregations verarbeiten Datensätze und geben berechnete Ergebnisse zurück. Aggregationsvorgänge gruppieren Werte aus mehreren Dokumenten zusammen und können verschiedene Vorgänge an den gruppierten Daten ausführen, um ein einzelnes Ergebnis zurückzugeben. MongoDB bietet drei Möglichkeiten für die Aggregation: die Aggregationspipeline, die Map-Reduction-Funktion und Einzelaggregationsmethoden.

Aus dem Mongo-Handbuch https://docs.mongodb.com/manual/aggregation/

Syntax

  • db.collection.aggregate (Pipeline, Optionen)

Parameter

Parameter Einzelheiten
Pipeline Array (Eine Folge von Datenaggregationsvorgängen oder -stufen)
Optionen Dokument (optional, nur verfügbar, wenn Pipeline als Array vorhanden ist)

Bemerkungen

Das Aggregations-Framework in MongoDB wird verwendet, um die allgemeine GROUP BY Funktionalität von SQL zu erreichen.

Berücksichtigen Sie für jedes Beispiel die folgenden Einfügungen in der Sammlung benannte transactions .

> db.transactions.insert({ cr_dr : "D", amount : 100, fee : 2});
> db.transactions.insert({ cr_dr : "C", amount : 100, fee : 2});
> db.transactions.insert({ cr_dr : "C", amount : 10,  fee : 2});
> db.transactions.insert({ cr_dr : "D", amount : 100, fee : 4});
> db.transactions.insert({ cr_dr : "D", amount : 10,  fee : 2});
> db.transactions.insert({ cr_dr : "C", amount : 10,  fee : 4});
> db.transactions.insert({ cr_dr : "D", amount : 100, fee : 2});

Anzahl

Wie erhalten Sie die Anzahl der Debit- und Kredittransaktionen? Eine Möglichkeit, dies zu tun, ist die Verwendung der Funktion count() wie unten beschrieben.

> db.transactions.count({cr_dr : "D"});

oder

> db.transactions.find({cr_dr : "D"}).length();

Was aber, wenn Sie die möglichen Werte von cr_dr Voraus nicht kennen. Hier kommt das Aggregations-Framework zum Einsatz. Siehe unten stehende Aggregatabfrage.

> db.transactions.aggregate( 
      [
          {
              $group : {
                  _id : '$cr_dr', // group by type of transaction
                // Add 1 for each document to the count for this type of transaction
                  count : {$sum : 1}
              }
          }
      ]
  );

Und das Ergebnis ist

{
    "_id" : "C",
    "count" : 3
}
{
    "_id" : "D",
    "count" : 5
}

Summe

Wie erhält man die Summe der amount ? Siehe unten stehende Aggregatabfrage.

> db.transactions.aggregate( 
     [
         {
             $group : {
                 _id : '$cr_dr',
                 count : {$sum : 1},    //counts the number
                 totalAmount : {$sum : '$amount'}    //sums the amount
             }
         }
     ] 
 );

Und das Ergebnis ist

{
    "_id" : "C",
    "count" : 3.0,
    "totalAmount" : 120.0
}
{
    "_id" : "D",
    "count" : 5.0,
    "totalAmount" : 410.0
}

Eine andere Version, die amount und fee summiert.

> db.transactions.aggregate(
      [
          {
              $group : {
                  _id : '$cr_dr',
                  count : {$sum : 1},
                  totalAmount : {$sum : { $sum : ['$amount', '$fee']}}
              }
          }
      ] 
  );

Und das Ergebnis ist

{
    "_id" : "C",
    "count" : 3.0,
    "totalAmount" : 128.0
}    
{
    "_id" : "D",
    "count" : 5.0,
    "totalAmount" : 422.0
}

Durchschnittlich

Wie erhalte ich den durchschnittlichen Betrag von Lastschriften und Gutschriften?

> db.transactions.aggregate(
    [
        {
            $group : {
                _id : '$cr_dr', // group by type of transaction (debit or credit)
                count : {$sum : 1},    // number of transaction for each type
                totalAmount : {$sum : { $sum : ['$amount', '$fee']}},    // sum
                averageAmount : {$avg : { $sum : ['$amount', '$fee']}}   // average
            }
        }
    ] 
)

Das Ergebnis ist

{
    "_id" : "C", // Amounts for credit transactions
    "count" : 3.0,
    "totalAmount" : 128.0,
    "averageAmount" : 40.0
}
{
    "_id" : "D", // Amounts for debit transactions
    "count" : 5.0,
    "totalAmount" : 422.0,
    "averageAmount" : 82.0
}

Operationen mit Arrays.

Wenn Sie mit den Dateneinträgen in Arrays arbeiten möchten, müssen Sie das Array zunächst abwickeln . Beim Abwickelvorgang wird für jeden Eintrag im Array ein Dokument erstellt. Wenn Sie viele Dokumente mit großen Arrays haben, wird die Anzahl der Dokumente explodieren.

{ "_id" : 1, "item" : "myItem1", sizes: [ "S", "M", "L"] }
{ "_id" : 2, "item" : "myItem2", sizes: [ "XS", "M", "XL"] }
    
db.inventory.aggregate( [ { $unwind : "$sizes" }] )

Ein wichtiger Hinweis ist, dass ein Dokument, das das Array nicht enthält, verloren geht. Ab Mongo 3.2 wird eine Abrolloption "preserveNullAndEmptyArrays" hinzugefügt. Diese Option stellt sicher, dass das Dokument erhalten bleibt, wenn das Array fehlt.

{ "_id" : 1, "item" : "myItem1", sizes: [ "S", "M", "L"] }
{ "_id" : 2, "item" : "myItem2", sizes: [ "XS", "M", "XL"] }
{ "_id" : 3, "item" : "myItem3" }
    
db.inventory.aggregate( [ { $unwind : { path: "$sizes", includeArrayIndex: "arrayIndex" } }] )

Spiel

Wie schreibe ich eine Abfrage, um alle Abteilungen zu erhalten, in denen das Durchschnittsalter der Beschäftigten unter oder 70000 USD liegt oder über 35 liegt?

Um dies zu erreichen, müssen wir eine Anfrage schreiben, die den Mitarbeitern entspricht, deren Gehalt weniger als oder gleich 70000 USD beträgt. Fügen Sie dann die Aggregatstufe hinzu, um die Mitarbeiter nach Abteilungen zu gruppieren. Fügen Sie dann einen Akkumulator mit einem Feld mit dem Namen "average_age" hinzu, um das Durchschnittsalter pro Abteilung mithilfe des $ avg-Akkumulators zu ermitteln. Unterhalb der vorhandenen $ match- und $ group-Aggregate fügen Sie ein weiteres $ match-Aggregat hinzu, sodass wir nur Ergebnisse mit einem average_age-Wert abrufen größer als oder gleich 35.

db.employees.aggregate([
  {"$match": {"salary": {"$lte": 70000}}},
  {"$group": {"_id": "$dept",
              "average_age": {"$avg": "$age"}
             }
  },
  {"$match": {"average_age": {"$gte": 35}}}
])

Das Ergebnis ist:

{
  "_id": "IT",
  "average_age": 31
}
{
  "_id": "Customer Service",
  "average_age": 34.5
}
{
  "_id": "Finance",
  "average_age": 32.5
}

Dokumente entfernen, die ein doppeltes Feld in einer Sammlung enthalten (Deduplizierung)

Beachten Sie, dass die Option allowDiskUse: true optional ist, dass jedoch Probleme mit dem Arbeitsspeicher vermieden werden, da diese Aggregation bei großer Sammlungsgröße einen speicherintensiven Vorgang darstellen kann.

var duplicates = [];

db.transactions.aggregate([
 { $group: { 
   _id: { cr_dr: "$cr_dr"},
   dups: { "$addToSet": "$_id" }, 
   count: { "$sum": 1 } 
 }
}, 
{ $match: { 
  count: { "$gt": 1 }   
}}
],allowDiskUse: true}
)              
.result          
.forEach(function(doc) {
  doc.dups.shift();   
  doc.dups.forEach( function(dupId){ 
    duplicates.push(dupId); 
  }
)    
})
// printjson(duplicates);     

// Remove all duplicates in one go    
db.transactions.remove({_id:{$in:duplicates}})


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow