Практика агрегатной агрегации MongoDB

Node.js MongoDB
Практика агрегатной агрегации MongoDB

Агрегация MongoDB

Агрегаты в MongoDB в основном используются для обработки данных (таких как среднее статистическое, суммирование и т. д.) и возврата результатов расчетных данных. Несколько похоже на count(*) в операторе sql.


метод агрегата()

Метод агрегации в MongoDB использует агрегат().

грамматика

Базовый формат синтаксиса методаaggregation() выглядит следующим образом:

db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)

Пример

Данные в сборнике следующие:

{
   _id: ObjectId(7df78ad8902c)
   title: 'MongoDB Overview', 
   description: 'MongoDB is no sql database',
   by_user: 'geekjc.com',
   url: 'http://www.geekjc.com',
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 100
},
{
   _id: ObjectId(7df78ad8902d)
   title: 'NoSQL Overview', 
   description: 'No sql database is very fast',
   by_user: 'geekjc.com',
   url: 'http://www.geekjc.com',
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 10
},
{
   _id: ObjectId(7df78ad8902e)
   title: 'Neo4j Overview', 
   description: 'cll is no sql database',
   by_user: 'cll',
   url: 'http://www.cll.com',
   tags: ['cll', 'database', 'NoSQL'],
   likes: 750
},

Теперь мы вычисляем количество статей, написанных каждым автором через указанный выше набор, используя агрегат () для вычисления результата следующим образом:

> db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
{
   "result" : [
      {
         "_id" : "geekjc.com",
         "num_tutorial" : 2
      },
      {
         "_id" : "cll",
         "num_tutorial" : 1
      }
   ],
   "ok" : 1
}
>

Приведенный выше пример похож на оператор sql:

 select by_user, count(*) from mycol group by by_user

В приведенном выше примере мы группируем данные по полю by_user и вычисляем сумму одинаковых значений поля by_user.

В следующей таблице показаны некоторые агрегатные выражения:

выражение описывать Пример
$sum Подсчитайте сумму. db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}])
$avg Рассчитать среднее db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}])
$min Получите минимальное значение, соответствующее всем документам в коллекции. db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}])
$max Получите максимальное значение, соответствующее всем документам в коллекции. db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}])
$push Вставляет значения в массив в результирующем документе. db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}])
$addToSet В результирующий документ вставляет значения в массив, но не создает копию. db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}])
$first Получить данные первого документа в соответствии с сортировкой ресурсных документов. db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}])
$last Получить последние данные документа в соответствии с сортировкой ресурсных документов db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}])

концепция трубы

Каналы обычно используются в Unix и Linux для передачи вывода текущей команды в качестве аргумента следующей команде.

Конвейер агрегации MongoDB принимает документы MongoDB после обработки одного конвейера и передает результат в следующий конвейер для обработки.Конвейерные операции повторяемы.

Выражение: обработайте входной документ и выведите его. Выражения не имеют состояния и могут использоваться только для оценки документов в текущем конвейере агрегации, а не других документов.

Здесь мы вводим несколько операций, обычно используемых в структуре агрегации:

  • $project: изменить структуру входного документа. Может использоваться для переименования, добавления или удаления полей, а также для создания результатов вычислений и вложенных документов.
  • $match: используется для фильтрации данных и вывода только тех документов, которые соответствуют условиям. $match использует стандартные операции запросов MongoDB.
  • $limit: используется для ограничения количества документов, возвращаемых конвейером агрегации MongoDB.
  • $skip: пропустить указанное количество документов в конвейере агрегации и вернуть оставшиеся документы.
  • $unwind: разбивает поле типа массива в документе на несколько записей, каждая из которых содержит значение в массиве.
  • $group: группирует документы в коллекции, которые можно использовать для статистических результатов.
  • $sort: сортирует входные документы и выводит их.
  • $geoNear: вывод упорядоченных документов рядом с географическим местоположением.

Пример оператора трубы

1. Экземпляр $проекта

db.article.aggregate(
    { $project : {
        title : 1 ,
        author : 1 ,
    }}
 );

В этом случае в результате всего три поля _id,tilte и author.По умолчанию включено поле _id.Если вы хотите исключить _id, вы можете сделать это:

db.article.aggregate(
    { $project : {
        _id : 0 ,
        title : 1 ,
        author : 1
    }});

2. Экземпляр $match

db.articles.aggregate( [
                        { $match : { score : { $gt : 70, $lte : 90 } } },
                        { $group: { _id: null, count: { $sum: 1 } } }
                       ] );

$match используется для получения записей с оценкой больше 70 и меньше или равной 90, а затем отправки подходящих записей оператору конвейера $group следующего этапа для обработки.

3. Экземпляр $skip

db.article.aggregate(
    { $skip : 5 });

После обработки оператором $skip pipe первые пять документов «отфильтровываются».

Проектная практика

с моим проектомУчебник компьютерщикаНапример, требование такое, мне нужно предоставить интерфейс для получения топ-20 самых популярных тегов (судя по количеству статей в тегах).

Структура схемы PostTags выглядит следующим образом:

posts:[{type:ObjectId,ref:'Post'}],
follower:[{type:ObjectId,ref:'User'}],
tagIcon: String,
title: String,
meta:{
      createAt:{
          type:Date,
          default:Date.now()
      },
      updateAt:{
          type:Date,
          default:Date.now()
      }
    }

Используя приведенное выше обучение, код выглядит следующим образом:

PostTags
  .aggregate([
    {
        $project : { posts_count: {$size: { "$ifNull": [ "$posts", [] ] }}, title: 1 }
    },
    {
        $sort: {"posts_count": -1}
    },
    {
        $limit: 20
    }
  ])
  .exec(function(err, tags) {
     ...
   })

Это также позволяет включать теги с пустыми статьями. Но есть недостаток (а иногда и преимущество): требуется вручную добавить все поля, которые нужно вернуть на шаге проекта. Как мне нужно название здесь.

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

Пополнить

$ifNull — это условное выражение, конкретное использование которого выглядит следующим образом:

условное выражение

1)$cond

上文中我们已经看到相关示例,它的作用等同于一个“三元表达式”,语法:

  $cond:{if : <boolean-expression>, then : <true-expression>,else : <false-expression> }

2)$ifNull

判定指定表达式是否为null,比如字段不存在(undefined)、值为null。语法:

 $ifNull:[<expression>,<return-value expression>]

 如果expression的值为null则返回“return-value”。