Поиск…


Вступление

Операции Aggregations обрабатывают записи данных и возвращают вычисленные результаты. Агрегация операций группирует значения из нескольких документов вместе и может выполнять множество операций над сгруппированными данными, чтобы вернуть один результат. MongoDB предоставляет три способа выполнения агрегации: конвейер агрегации, функцию уменьшения карты и одноцелевые методы агрегирования.

Из руководства Mongo https://docs.mongodb.com/manual/aggregation/

Синтаксис

  • db.collection.aggregate (конвейер, параметры)

параметры

параметр подробности
трубопровод array (последовательность операций или этапов агрегации данных)
опции document (необязательно, доступно, только если конвейер представлен как массив)

замечания

Агрегирующая структура в MongoDB используется для достижения общей функциональности SQL GROUP BY .

В каждом примере рассмотрите следующие вставки в коллекции названных transactions .

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

подсчитывать

Как вы получаете количество дебетовых и кредитных транзакций? Один из способов сделать это - использовать функцию count() как показано ниже.

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

или же

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

Но что, если вы не знаете возможных значений cr_dr . Здесь возникает задача создания системы агрегирования. См. Ниже приведенный запрос.

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

И результат

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

сумма

Как получить суммирование amount ? См. Ниже совокупный запрос.

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

И результат

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

Другая версия, которая суммирует amount и fee .

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

И результат

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

Средний

Как получить среднюю сумму дебетовых и кредитных транзакций?

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

В результате

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

Операции с массивами.

Когда вы хотите работать с записями данных в массивах, вам сначала нужно развернуть массив. Операция размотки создает документ для каждой записи в массиве. Когда у вас много документов с большими массивами, вы увидите взрыв в количестве документов.

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

Важно отметить, что когда документ не содержит массив, он будет потерян. Из mongo 3.2 и выше есть опция разматывания «preserveNullAndEmptyArrays». Этот параметр гарантирует, что документ сохраняется, когда массив отсутствует.

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

Матч

Как написать запрос, чтобы получить все отделы, где средний возраст сотрудников, составляющих менее или 70000 долларов, больше или равен 35?

Для этого нам нужно написать запрос для соответствия сотрудникам, у которых есть зарплата, которая меньше или равна 70000 долларов США. Затем добавьте совокупный этап для группировки сотрудников отделом. Затем добавьте аккумулятор с полем, например, average_age, чтобы найти средний возраст для одного отдела с помощью накопителя $ avg и ниже существующих $ match и $ group aggregates добавьте еще один агрегат $ match, чтобы мы только получали результаты со средним значением, которое больше или равно 35.

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

Результат:

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

Удалите документы, которые имеют дублирующее поле в коллекции (dedupe)

Обратите внимание, что параметр allowDiskUse: true является необязательным, но поможет смягчить проблемы с памятью, поскольку это агрегирование может быть интенсивной операцией с памятью, если размер вашей коллекции большой, поэтому я рекомендую всегда использовать его.

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
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow