MongoDB
Aggregatie
Zoeken…
Invoering
Aggregations
bewerkingen verwerken gegevensrecords en retourneren berekende resultaten. Aggregatiebewerkingen groeperen waarden uit meerdere documenten samen en kunnen verschillende bewerkingen uitvoeren op de gegroepeerde gegevens om een enkel resultaat te retourneren. MongoDB biedt drie manieren om aggregatie uit te voeren: de aggregatiepijplijn, de kaartreductiefunctie en aggregatiemethoden voor één doel.
Uit Mongo-handleiding https://docs.mongodb.com/manual/aggregation/
Syntaxis
- db.collection.aggregate (pijplijn, opties)
parameters
Parameter | Details |
---|---|
pijpleiding | array (een reeks gegevensverzamelhandelingen of -stadia) |
opties | document (optioneel, alleen beschikbaar als pijplijn aanwezig is als een array) |
Opmerkingen
Aggregatieraamwerk in MongoDB wordt gebruikt om gemeenschappelijke GROUP BY
functionaliteit van SQL te bereiken.
Overweeg de volgende invoegingen in de verzameling met de naam transactions
voor elk voorbeeld.
> 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});
tellen
Hoe krijg je het aantal Debet- en Credit-transacties? Een manier om dit te doen is door de functie count()
te gebruiken zoals hieronder.
> db.transactions.count({cr_dr : "D"});
of
> db.transactions.find({cr_dr : "D"}).length();
Maar wat als u de mogelijke waarden van cr_dr
vooraf niet kent. Hier komt het aggregatiekader om te spelen. Zie de onderstaande samengevoegde zoekopdracht.
> 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}
}
}
]
);
En het resultaat is
{
"_id" : "C",
"count" : 3
}
{
"_id" : "D",
"count" : 5
}
Som
Hoe de som van het amount
? Zie de onderstaande verzamelquery.
> db.transactions.aggregate(
[
{
$group : {
_id : '$cr_dr',
count : {$sum : 1}, //counts the number
totalAmount : {$sum : '$amount'} //sums the amount
}
}
]
);
En het resultaat is
{
"_id" : "C",
"count" : 3.0,
"totalAmount" : 120.0
}
{
"_id" : "D",
"count" : 5.0,
"totalAmount" : 410.0
}
Een andere versie die amount
en fee
somt.
> db.transactions.aggregate(
[
{
$group : {
_id : '$cr_dr',
count : {$sum : 1},
totalAmount : {$sum : { $sum : ['$amount', '$fee']}}
}
}
]
);
En het resultaat is
{
"_id" : "C",
"count" : 3.0,
"totalAmount" : 128.0
}
{
"_id" : "D",
"count" : 5.0,
"totalAmount" : 422.0
}
Gemiddelde
Hoe het gemiddelde bedrag van debet- en krediettransacties te krijgen?
> 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
}
}
]
)
Het resultaat is
{
"_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
}
Bewerkingen met arrays.
Wanneer u wilt werken met de invoer van gegevens in arrays moet u eerst tot rust komen de array. De afwikkelbewerking maakt een document voor elk item in de array. Wanneer u veel documenten met grote arrays hebt, ziet u een explosie van het aantal documenten.
{ "_id" : 1, "item" : "myItem1", sizes: [ "S", "M", "L"] }
{ "_id" : 2, "item" : "myItem2", sizes: [ "XS", "M", "XL"] }
db.inventory.aggregate( [ { $unwind : "$sizes" }] )
Een belangrijke mededeling is dat wanneer een document de array niet bevat, deze verloren gaat. Vanaf mongo 3.2 en hoger is er een afroloptie "preserveNullAndEmptyArrays" toegevoegd. Deze optie zorgt ervoor dat het document behouden blijft wanneer de array ontbreekt.
{ "_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" } }] )
Bij elkaar passen
Hoe een vraag te schrijven om alle afdelingen te krijgen waar de gemiddelde leeftijd van werknemers die minder dan of $ 70000 verdienen, groter is dan of gelijk aan 35?
Om dat te bereiken moeten we een vraag schrijven die overeenkomt met werknemers die een salaris hebben dat lager is dan of gelijk is aan $ 70000. Voeg vervolgens de geaggregeerde fase toe om de werknemers per afdeling te groeperen. Voeg vervolgens een accumulator toe met een veld met de naam bijv. Gemiddelde_datum om de gemiddelde leeftijd per afdeling te vinden met behulp van de $ avg-accumulator en voeg onder de bestaande $ match en $ groepsaggregaten nog een $ match-aggregaat toe zodat we alleen resultaten ophalen met een gemiddelde_waarde die is groter dan of gelijk aan 35.
db.employees.aggregate([
{"$match": {"salary": {"$lte": 70000}}},
{"$group": {"_id": "$dept",
"average_age": {"$avg": "$age"}
}
},
{"$match": {"average_age": {"$gte": 35}}}
])
Het resultaat is:
{
"_id": "IT",
"average_age": 31
}
{
"_id": "Customer Service",
"average_age": 34.5
}
{
"_id": "Finance",
"average_age": 32.5
}
Documenten verwijderen met een dubbel veld in een verzameling (dedupe)
Let op: de optie allowDiskUse: true is optioneel, maar helpt geheugenproblemen te verminderen, omdat deze aggregatie een geheugenintensieve bewerking kan zijn als uw verzameling groot is - dus ik raad aan deze altijd te gebruiken.
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}})