Sök…


Introduktion

Aggregations bearbetar dataregister och returnerar beräknade resultat. Aggregationsoperationsgruppvärden från flera dokument tillsammans och kan utföra en mängd olika operationer på den grupperade datan för att returnera ett enda resultat. MongoDB tillhandahåller tre sätt att utföra aggregering: aggregeringsrörledningen, kartminskningsfunktionen och aggregeringsmetoder med en enda syfte.

Från Mongo-manualen https://docs.mongodb.com/manual/aggregation/

Syntax

  • db.collection.aggregate (pipeline, optioner)

parametrar

Parameter detaljer
rörledning array (En sekvens av datainsamlingsoperationer eller -steg)
alternativ dokument (valfritt, endast tillgängligt om pipeline finns som en matris)

Anmärkningar

Aggregationsramverk i MongoDB används för att uppnå gemensam GROUP BY funktion i SQL.

Tänk på följande infogningar i samlade namngivna transactions för varje exempel.

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

Räkna

Hur får du antalet debiterings- och kredittransaktioner? Ett sätt att göra det är att använda funktionen count() enligt nedan.

> db.transactions.count({cr_dr : "D"});

eller

> db.transactions.find({cr_dr : "D"}).length();

Men tänk om du inte känner till de möjliga värdena på cr_dr förhand. Här kommer aggregeringsramen att spela. Se den sammanlagda frågan nedan.

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

Och resultatet är

{
    "_id" : "C",
    "count" : 3
}
{
    "_id" : "D",
    "count" : 5
}

Summa

Hur får man summeringen av amount ? Se den sammanlagda frågan nedan.

> db.transactions.aggregate( 
     [
         {
             $group : {
                 _id : '$cr_dr',
                 count : {$sum : 1},    //counts the number
                 totalAmount : {$sum : '$amount'}    //sums the amount
             }
         }
     ] 
 );

Och resultatet är

{
    "_id" : "C",
    "count" : 3.0,
    "totalAmount" : 120.0
}
{
    "_id" : "D",
    "count" : 5.0,
    "totalAmount" : 410.0
}

En annan version som summerar amount och fee .

> db.transactions.aggregate(
      [
          {
              $group : {
                  _id : '$cr_dr',
                  count : {$sum : 1},
                  totalAmount : {$sum : { $sum : ['$amount', '$fee']}}
              }
          }
      ] 
  );

Och resultatet är

{
    "_id" : "C",
    "count" : 3.0,
    "totalAmount" : 128.0
}    
{
    "_id" : "D",
    "count" : 5.0,
    "totalAmount" : 422.0
}

Medel

Hur får man det genomsnittliga beloppet för debet- och kredittransaktioner?

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

Resultatet är

{
    "_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
}

Operationer med matriser.

När du vill arbeta med datainmatningarna i matriser måste du först lossa matrisen. Avrullningsfunktionen skapar ett dokument för varje post i matrisen. När du har många dokument med stora matriser ser du en explosion i antal dokument.

{ "_id" : 1, "item" : "myItem1", sizes: [ "S", "M", "L"] }
{ "_id" : 2, "item" : "myItem2", sizes: [ "XS", "M", "XL"] }
    
db.inventory.aggregate( [ { $unwind : "$sizes" }] )

Ett viktigt meddelande är att när ett dokument inte innehåller matrisen kommer det att gå förlorat. Från mongo 3.2 och uppåt finns ett avkopplingsalternativ "preserveNullAndEmptyArrays" till. Det här alternativet ser till att dokumentet bevaras när matrisen saknas.

{ "_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" } }] )

Match

Hur skriver man en fråga för att få alla avdelningar där medelåldern för anställda som gör mindre än eller $ 70000 är större än eller lika med 35?

För att vi måste skriva en fråga för att matcha anställda som har en lön som är mindre än eller lika med $ 70000. Lägg sedan till det sammanlagda skedet för att gruppera de anställda vid avdelningen. Lägg sedan till en ackumulator med ett fält som heter t.ex. gemiddelde_age för att hitta genomsnittsåldern per avdelning med hjälp av $ avg-ackumulatorn och under den befintliga $ -matchen och $ -gruppsaggregat lägger till ytterligare $ matchningsaggregat så att vi bara hämtar resultat med en genomsnittlig_age som är greather än eller lika med 35.

db.employees.aggregate([
  {"$match": {"salary": {"$lte": 70000}}},
  {"$group": {"_id": "$dept",
              "average_age": {"$avg": "$age"}
             }
  },
  {"$match": {"average_age": {"$gte": 35}}}
])

Resultatet är:

{
  "_id": "IT",
  "average_age": 31
}
{
  "_id": "Customer Service",
  "average_age": 34.5
}
{
  "_id": "Finance",
  "average_age": 32.5
}

Ta bort dokument som har ett duplikatfält i en samling (dedupe)

Observera att tillvalet allowDiskUse: true är valfritt men kommer att hjälpa till att minska problem i minnet eftersom denna aggregering kan vara en minnesintensiv operation om din samlingsstorlek är stor - så jag rekommenderar att du alltid använder den.

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow