Szukaj…


Wprowadzenie

Operacje Aggregations przetwarzają rekordy danych i zwracają obliczone wyniki. Operacje agregujące grupują wartości z wielu dokumentów razem i mogą wykonywać różne operacje na zgrupowanych danych w celu zwrócenia pojedynczego wyniku. MongoDB zapewnia trzy sposoby przeprowadzania agregacji: potok agregacji, funkcja zmniejszania mapy i metody agregacji o jednym celu.

Z podręcznika Mongo https://docs.mongodb.com/manual/aggregation/

Składnia

  • db.collection.aggregate (potok, opcje)

Parametry

Parametr Detale
rurociąg tablica (sekwencja operacji lub etapów agregacji danych)
opcje dokument (opcjonalnie, dostępny tylko wtedy, gdy potok występuje jako tablica)

Uwagi

Struktura agregacji w MongoDB służy do osiągnięcia wspólnej funkcjonalności GROUP BY SQL.

Rozważ następujące wstawki w nazwanych transactions kolekcji dla każdego przykładu.

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

Liczyć

Jak uzyskać liczbę transakcji debetowych i kredytowych? Jednym ze sposobów na to jest użycie funkcji count() jak poniżej.

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

lub

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

Ale co, jeśli nie znasz możliwych wartości cr_dr z góry. Tutaj zaczyna się gra Aggregation Framework. Zobacz poniższe zapytanie agregujące.

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

I wynik jest taki

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

Suma

Jak uzyskać sumę amount ? Zobacz poniższe zapytanie zagregowane.

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

I wynik jest taki

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

Kolejna wersja, która sumuje amount i fee .

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

I wynik jest taki

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

Średni

Jak uzyskać średnią kwotę transakcji debetowych i kredytowych?

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

Wynik to

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

Operacje na tablicach.

Jeśli chcesz pracować z wpisami danych w tablicach, musisz najpierw odłączyć tablicę. Operacja odwijania tworzy dokument dla każdego wpisu w tablicy. Kiedy masz dużo dokumentów z dużymi tablicami, zobaczysz eksplozję w liczbie dokumentów.

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

Ważną uwagą jest to, że jeśli dokument nie zawiera tablicy, zostanie utracony. Od wersji 3.2 Mongo jest dodana opcja odprężania „preserveNullAndEmptyArrays”. Ta opcja zapewnia zachowanie dokumentu w przypadku braku tablicy.

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

Mecz

Jak napisać zapytanie, aby uzyskać wszystkie działy, w których średni wiek pracowników zarabiających mniej niż 70000 USD jest wyższy lub równy 35?

W tym celu musimy napisać zapytanie pasujące do pracowników, których wynagrodzenie jest niższe lub równe 70000 USD. Następnie dodaj etap agregacji, aby pogrupować pracowników według działów. Następnie dodaj akumulator z polem o nazwie np. Average_age, aby znaleźć średni wiek na dział przy użyciu akumulatora $ Avg i poniżej istniejącego $ match, a agregaty $ group dodaj kolejny agregat $ match, abyśmy otrzymywali wyniki tylko ze średnią większy lub równy 35.

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

Wynik to:

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

Usuń dokumenty, które mają zduplikowane pole w kolekcji (dedupe)

Zauważ, że opcja allowDiskUse: true jest opcjonalna, ale pomoże złagodzić problemy z pamięcią, ponieważ ta agregacja może być operacją intensywnie korzystającą z pamięci, jeśli Twój rozmiar kolekcji jest duży - dlatego zalecam, aby zawsze go używać.

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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow