MongoDB
Agrégation
Recherche…
Introduction
Aggregations
opérations d' Aggregations
traitent les enregistrements de données et renvoient les résultats calculés. Les opérations d'agrégation regroupent les valeurs de plusieurs documents et peuvent effectuer diverses opérations sur les données groupées pour renvoyer un seul résultat. MongoDB propose trois méthodes pour effectuer l'agrégation: le pipeline d'agrégation, la fonction de réduction de carte et les méthodes d'agrégation à un seul objectif.
À partir du manuel Mongo https://docs.mongodb.com/manual/aggregation/
Syntaxe
- db.collection.aggregate (pipeline, options)
Paramètres
Paramètre | Détails |
---|---|
pipeline | array (Une séquence d'opérations ou d'étapes d'agrégation de données) |
options | document (facultatif, disponible uniquement si le pipeline est présent sous forme de tableau) |
Remarques
La structure d'agrégation dans MongoDB est utilisée pour obtenir la fonctionnalité GROUP BY
commune de SQL.
Considérez les insertions suivantes dans les transactions
nommées collection pour chaque exemple.
> 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});
Compter
Comment obtenez-vous le nombre d'opérations de débit et de crédit? Une façon de le faire est d'utiliser la fonction count()
comme ci-dessous.
> db.transactions.count({cr_dr : "D"});
ou
> db.transactions.find({cr_dr : "D"}).length();
Mais que faire si vous ne connaissez pas les valeurs possibles de cr_dr
upfront. Ici, le cadre d'agrégation vient jouer. Voir la requête d'agrégation ci-dessous.
> 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}
}
}
]
);
Et le résultat est
{
"_id" : "C",
"count" : 3
}
{
"_id" : "D",
"count" : 5
}
Somme
Comment obtenir la somme du amount
? Voir la requête globale ci-dessous.
> db.transactions.aggregate(
[
{
$group : {
_id : '$cr_dr',
count : {$sum : 1}, //counts the number
totalAmount : {$sum : '$amount'} //sums the amount
}
}
]
);
Et le résultat est
{
"_id" : "C",
"count" : 3.0,
"totalAmount" : 120.0
}
{
"_id" : "D",
"count" : 5.0,
"totalAmount" : 410.0
}
Une autre version qui calcule le amount
et les fee
.
> db.transactions.aggregate(
[
{
$group : {
_id : '$cr_dr',
count : {$sum : 1},
totalAmount : {$sum : { $sum : ['$amount', '$fee']}}
}
}
]
);
Et le résultat est
{
"_id" : "C",
"count" : 3.0,
"totalAmount" : 128.0
}
{
"_id" : "D",
"count" : 5.0,
"totalAmount" : 422.0
}
Moyenne
Comment obtenir le montant moyen des transactions de débit et de crédit?
> 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
}
}
]
)
Le résultat est
{
"_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
}
Opérations avec des tableaux.
Lorsque vous voulez travailler avec les entrées de données dans les tableaux, vous devez d'abord dérouler le tableau. L'opération de déroulement crée un document pour chaque entrée du tableau. Lorsque vous avez beaucoup de documents avec de grands tableaux, vous verrez une explosion du nombre de documents.
{ "_id" : 1, "item" : "myItem1", sizes: [ "S", "M", "L"] }
{ "_id" : 2, "item" : "myItem2", sizes: [ "XS", "M", "XL"] }
db.inventory.aggregate( [ { $unwind : "$sizes" }] )
Une remarque importante est que lorsqu'un document ne contient pas le tableau, il sera perdu. À partir de mongo 3.2, il y a une option de déroulage "preserveNullAndEmptyArrays" ajoutée. Cette option garantit que le document est conservé lorsque le tableau est manquant.
{ "_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" } }] )
Rencontre
Comment rédiger une requête pour obtenir tous les départements où l'âge moyen des employés gagnant moins de 70000 $ est supérieur ou égal à 35?
Pour cela, nous devons rédiger une requête afin de correspondre aux employés dont le salaire est inférieur ou égal à 70000 dollars. Ajoutez ensuite l'étape de regroupement pour regrouper les employés par le service. Ajoutez ensuite un accumulateur avec un champ nommé par exemple plus grand que ou égal à 35.
db.employees.aggregate([
{"$match": {"salary": {"$lte": 70000}}},
{"$group": {"_id": "$dept",
"average_age": {"$avg": "$age"}
}
},
{"$match": {"average_age": {"$gte": 35}}}
])
Le résultat est:
{
"_id": "IT",
"average_age": 31
}
{
"_id": "Customer Service",
"average_age": 34.5
}
{
"_id": "Finance",
"average_age": 32.5
}
Supprimer les documents qui ont un champ en double dans une collection (dedupe)
Notez que l'option allowDiskUse: true est facultative mais aidera à atténuer les problèmes de mémoire, car cette agrégation peut nécessiter beaucoup de mémoire si la taille de votre collection est importante. Je vous recommande donc de toujours l'utiliser.
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}})