Агрегация 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”。