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}})


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow