MongoDB
Anhäufung
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}})