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


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow