theory_05__aggregation.md

Занятие 84Markdown117 строк

← К репозиторию занятия · 14__MongoDB_introduction/theory_05__aggregation.md

Агрегация в MongoDB

Как запустить агрегацию?

В MongoDB Compass - это вкладка aggregation; В mongo shell или mongosh — используется метод aggregation().

Отличия от SQL

Агрегация в MongoDB несколько отличается от агрегации в SQL.

Главная причина - наличие pipeline (конвейера), который позволяет последовательно указать несколько операций, где результаты (выходные документы) предыдущей операции будут входными документами для последующей.

Таким образом, все БЕЗ ИСКЛЮЧЕНИЯ запросы MongoDB можно выразить через также через агрегацию.

Задание для примера: Выбрать документы, где возраст сотрудника больше 30 лет. Оставить только имя и зарплату, отсортировать по з/п по убыванию. Пропустить первые 10 документов, и вывести следующие 10.

  • Обычный запрос
db.getCollection('employees').find(
    { age: { $gt: 30 } },
    { name: 1, salary: 1, _id: 0 }
  )
  .sort({ salary: -1 })
  .skip(10)
  .limit(10);

Запрос через агрегацию:

db.employees.aggregate(
    [
        { "$match": { "age": { "$gt": 30 } } },
        { "$project": { "_id": 0, "name": 1, "salary": 1 } },
        { "$sort": { "salary": -1 } },
        { "$skip": 10 },
        { "$limit": 10 }
    ]
);

Непосредственно группировка

Бывает двух видов:

  • $group - похожа на GROUP BY
  • $sortByCount - одновременно:
    • группирует,
    • сортирует по убыванию
    • и подсчитывает кол-во документов в каждой группе
    • (те есть фактически это две стадии: $group и $sort)

Стадия $group

Синтаксис:
{
  _id: expression,
  fieldN: {
    accumulatorN: expressionN
  }
}

где

  • expression - поле, по которому происходит группировка. Если оно null, значит группировка идёт по всей коллекции
  • fieldN - произвольное имя агрегированного значения
  • expressionN - поле, по которому идёт агрегация
  • accumulatorN - функция-агрегатор
ОператорНазначениеПример использования
$sumСуммирует значения в группе"$sum": "$price"
$avgВычисляет среднее значение"$avg": "$age"
$minНаходит минимальное значение"$min": "$score"
$maxНаходит максимальное значение"$max": "$score"
$firstПервое значение в группе (в порядке поступления)"$first": "$name"
$lastПоследнее значение в группе"$last": "$name"
$pushДобавляет значение в массив"$push": "$tag"
$addToSetДобавляет уникальные значения в массив (без дубликатов)"$addToSet": "$tag"
$countПодсчёт количества документов (через $sum: 1)"$sum": 1
Пример:

Найти средний возраст всех сотрудников по отделам:

{
    $group: {
        _id: "$department_id",
        avg_age: { $avg: "$age" }
    }
}

Найти средний возраст всех сотрудников по всех фирме (в смысле, по всей коллекции):

{
    $group: {
        _id: null,
        avg_age: { $avg: "$age" }
    }
}

Стадия $sortByCount

Синтаксис:
{
    $sortByCount:  <expression>
}

где expression - поле, по которому идёт группировка, подсчёт значений и их сортировка (то есть в поле агрегации просто пишется поле с долларом, в кавычках, но БЕЗ скобок!)

ВАЖНО: $sortByCount не используется для вычисления max/min значений. Для этого используется $group с $max или $min.