Агрегация в информатике относится к процессу проверки контента, обработки и категоризации соответствующих данных и вывода результатов. Агрегация в MongoDB относится к процессу одновременной обработки, фильтрации и категоризации данных из нескольких документов и вывода результатов. В процессе операции агрегации данные подобны воде, протекающей по секционному конвейеру, поэтому агрегация в MongoDB также называется потоковой агрегацией.
MongoDB предоставляет несколько методов агрегации:
- Aggregation Pipeline
- Map-Reduce
- простая агрегация
Далее мы всесторонне рассмотрим агрегаты в MongoDB.
Aggregation Pipeline
Конвейер агрегации также известен как конвейер агрегации. Разработчики могут передавать несколько документов в одинStageсостоит изPipeline,КаждыйStageРезультат обработки будет передан следующемуStageсредний, последнийStageРезультатом обработки является весьPipelineВывод.
Синтаксис создания конвейера агрегации следующий:
db.collection.aggregate( [ { <stage> }, ... ] )
MongoDB предоставляет 23 видаStage,Они есть:
| Stage | описывать |
|---|---|
$addFields |
Добавьте новые поля в документ. |
$bucket |
Группирует входящие документы в соответствии с указанным выражением и границами корзины. |
$bucketAuto |
Автоматически определяет границы корзины, классифицируя входящие документы по определенному количеству групп на основе заданного выражения. |
$collStats |
Возвращает статистику о коллекции или представлении. |
$count |
Возвращает количество документов для этого этапа конвейера агрегации. |
$facet |
Обращайтесь с несколькими операциями агрегации в пределах одного фазы одного и того же набора входных документов. |
$geoNear |
Возвращает упорядоченный поток документов на основе близости к геопространственной точке. |
$graphLookup |
Выполните рекурсивный поиск по коллекции. |
$group |
Группирует документы по указанному выражению идентификатора. |
$indexStats |
Возвращает информацию индекса для коллекции. |
$limit |
Пройти немодифицированные первые N документы в трубопровод. |
$listSessions |
списокsystem.sessionsВсе сессии коллекции. |
$lookup |
Выполните левое внешнее соединение с другой коллекцией в той же базе данных. |
$match |
Фильтровать документы, позволяя передавать на следующий этап конвейера только соответствующие документы. |
$out |
Записывает результирующий документ конвейера агрегации в указанную коллекцию, которая должна быть последним этапом конвейера. |
$project |
Добавьте новые поля в документ или удалите существующие поля. |
$redact |
Может использоваться для реализации редактирования на уровне полей. |
$replaceRoot |
Заменить документ на указанный встроенный в документ. Это заменит любое существующее поле во входном документе, включая_idполе. Указывает документ, внедренный во входной документ, для продвижения внедренного документа на верхний уровень. |
$sample |
Случайным образом выбирает указанное количество документов из ввода. |
$skip |
Пропустить первые n документов и передать оставшиеся документы без изменений на следующий этап. |
$sort |
Переупорядочивает поток документов по указанному ключу сортировки. Меняется только порядок, файл остается прежним. Для каждого входного документа выведите один документ. |
$sortByCount |
Сгруппируйте входящие документы, затем подсчитайте количество документов в каждой отдельной группе. |
$unwind |
Деструктуризация полей массива в документе. |
Документация,StageиPipelineОтношение показано на следующем рисунке:
$match,$sampleи$projectподожди триStageи процесс вывода. Общие термины агрегации в SQL:WHERE,SUMиCOUNTЖдать. В следующей таблице описаны общие термины, функции и концепции агрегации SQL, а также соответствующие им операторы MongoDB илиStage.
| SQL | MongoDB |
|---|---|
| WHERE | $match |
| GROUP BY | $group |
| HAVING | $match |
| SELECT | $project |
| ORDER BY | $sort |
| LIMIT | $limit |
| SUM() | $sum |
| COUNT() |
$sum$sortByCount
|
| join | $lookup |
Ниже разберемся на примереAggregate,StageиPipelineОтношения между.
Простая концепция
$matchОписание гласит: «Фильтровать документы, позволяя передавать на следующий этап конвейера только соответствующие документы». Его синтаксис следующий:
{ $match: { <query> } }
Прежде чем приступить к обучению, нам необходимо подготовить следующие данные:
> db.artic.insertMany([
... { "_id" : 1, "author" : "dave", "score" : 80, "views" : 100 },
... { "_id" : 2, "author" : "dave", "score" : 85, "views" : 521 },
... { "_id" : 3, "author" : "anna", "score" : 60, "views" : 706 },
... { "_id" : 4, "author" : "line", "score" : 55, "views" : 300 }
... ])
Тогда мы строим только одинStageизPipeline, чтобы отфильтроватьauthorзаdaveдокументация. Соответствующий пример выглядит следующим образом:
> db.artic.aggregate([
... {$match: {author: "dave"}}
... ])
{ "_id" : 1, "author" : "dave", "score" : 80, "views" : 100 }
{ "_id" : 2, "author" : "dave", "score" : 85, "views" : 521 }
Если вы хотите создать дваStageизPipeline, затем вaggregateдобавитьStageВот и все. Сейчас такая потребность: сбор статистикиarticсерединаscoreбольше, чем70и меньше чем90количество документов. Это требование выполняется в два этапа:
- Отфильтруйте документы, соответствующие вашим требованиям
- Подсчитайте количество документов
Агрегация идеально подходит для этой многоэтапной операции. В этом сценарии нам нужно использовать$match,$groupэти двоеStage, а затем с помощью агрегатного выражения$sumВ совокупности соответствующие примеры выглядят следующим образом:
> db.artic.aggregate([
... {$match: {score: {$gt: 70, $lt: 90}}},
... {$group: {_id: null, number: {$sum: 1}}}
... ])
{ "_id" : null, "number" : 2 }
Полный процесс этого примера может быть представлен следующей схемой:
Aggregate,StageиPipelineиметь определенное понимание. Далее мы изучим общиеStageсинтаксис и использование.
Общая сцена
sample
$sampleРоль состоит в том, чтобы случайным образом выбрать указанное количество документов из ввода, и его синтаксис выглядит следующим образом:
{ $sample: { size: <positive integer> } }
Предположим, вы хотите получить из коллекцииarticИз списка случайным образом выбираются два документа, соответствующие примеры таковы:
> db.artic.aggregate([
... {$sample: {size: 2}}
... ])
{ "_id" : 1, "author" : "dave", "score" : 80, "views" : 100 }
{ "_id" : 3, "author" : "anna", "score" : 60, "views" : 706 }
sizeСоответствующее значение должно быть целым положительным числом. Если вы введете отрицательное число, вы получите сообщение об ошибке:size argument to $sample must not be negative. Обратите внимание, что когда значение превышает количество документов в коллекции, возвращаются все документы в коллекции, но порядок документов является случайным.
project
$projectРоль заключается в фильтрации полей в документе, что аналогично операции проецирования, но результаты обработки будут переданы на следующий этап. Его синтаксис следующий:
{ $project: { <specification(s)> } }
Подготовьте следующие данные:
> db.projects.save(
{_id: 1, title: "篮球训练营青春校园活动开始啦", numb: "A829Sck23", author: {last: "quinn", first: "James"}, hot: 35}
)
ПредположениеPipelineследующий вStageПросто нужна документацияtitleиauthorполя, соответствующие примеры выглядят следующим образом:
> db.projects.aggregate([{$project: {title: 1, author: 1}}])
{ "_id" : 1, "title" : "篮球训练营青春校园活动开始啦", "author" : { "last" : "quinn", "first" : "James" } }
0и1могут существовать одновременно. Соответствующий пример выглядит следующим образом:
> db.projects.aggregate([{$project: {title: 1, author: 1, _id: 0}}])
{ "title" : "篮球训练营青春校园活动开始啦", "author" : { "last" : "quinn", "first" : "James" } }
trueравно1,falseравно0, вы также можете смешивать логические значения и числа, соответствующие примеры выглядят следующим образом:
> db.projects.aggregate([{$project: {title: 1, author: true, _id: false}}])
{ "title" : "篮球训练营青春校园活动开始啦", "author" : { "last" : "quinn", "first" : "James" } }
Если вы хотите исключить указанные поля, то в$projectустановить его на0илиfalseТогда соответствующий пример выглядит следующим образом:
> db.projects.aggregate([{$project: {author: false, _id: false}}])
{ "title" : "篮球训练营青春校园活动开始啦", "numb" : "A829Sck23", "hot" : 35 }
$projectТакже работает со встроенными документами. заauthorполя, иногда нам просто нужноFirstNameилиLastname, соответствующий пример выглядит следующим образом:
> db.projects.aggregate([{$project: {author: {"last": false}, _id: false, numb: 0}}])
{ "title" : "篮球训练营青春校园活动开始啦", "author" : { "first" : "James" }, "hot" : 35 }
использовать здесь{author: {"last": false}}ОтфильтрованоLastName, но держиfirst.
Вышеупомянутое$projectВведение в основное использование и функции , больше с$projectСоответствующие знания можно найти в официальной документации$project.
lookup
$lookupРоль заключается в выполнении левого внешнего соединения коллекций в той же базе данных, и его синтаксис выглядит следующим образом:
{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}
Левое внешнее соединение выглядит как следующий оператор псевдо-SQL:
SELECT *, <output array field>
FROM collection WHERE <output array field> IN (
SELECT * FROM <collection to join> WHERE
<foreignField>= <collection.localField>);
lookupНиже приведены поддерживаемые команды и соответствующие им описания:
| поле | описывать |
|---|---|
from |
Задает имя коллекции. |
localField |
Укажите ввод$lookupполя в . |
foreignField |
уточнитьfromПоля документа в данной коллекции. |
as |
Задает имя нового массива полей, добавляемых во входной документ. Новое поле массива содержит fromсовпадающие документы в коллекции.Если указанное имя уже существует во входном документе, существующее поле будет перезаписано. |
Подготовьте следующие данные:
> db.sav.insert([
{ "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 },
{ "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 },
{ "_id" : 3 }
])
> db.avi.insert([
{ "_id" : 1, "sku" : "almonds", description: "product 1", "instock" : 120 },
{ "_id" : 2, "sku" : "bread", description: "product 2", "instock" : 80 },
{ "_id" : 3, "sku" : "cashews", description: "product 3", "instock" : 60 },
{ "_id" : 4, "sku" : "pecans", description: "product 4", "instock" : 70 },
{ "_id" : 5, "sku": null, description: "Incomplete" },
{ "_id" : 6 }
])
Предположим, вы хотите присоединиться к коллекциямsavсерединаitemи коллекцияaviсерединаsku, и назовите объединенный результат какsavi. Соответствующий пример выглядит следующим образом:
> db.sav.aggregate([
{
$lookup:
{
from: "avi",
localField: "item",
foreignField: "sku",
as: "savi"
}
}
])
После выполнения команды вывод будет следующим:
{
"_id" : 1,
"item" : "almonds",
"price" : 12,
"quantity" : 2,
"savi" : [
{ "_id" : 1, "sku" : "almonds", "description" : "product 1", "instock" : 120 }
]
}
{
"_id" : 2,
"item" : "pecans",
"price" : 20,
"quantity" : 1,
"savi" : [
{ "_id" : 4, "sku" : "pecans", "description" : "product 4", "instock" : 70 }
]
}
{
"_id" : 3,
"savi" : [
{ "_id" : 5, "sku" : null, "description" : "Incomplete" },
{ "_id" : 6 }
]
}
Приведенная выше операция соединения эквивалентна следующему псевдо-SQL:
SELECT *, savi
FROM sav
WHERE savi IN (SELECT *
FROM avi
WHERE sku= sav.item);
ВышеупомянутоеlookupВведение в основное использование и функции , больше сlookupСоответствующие знания можно найти в официальной документацииlookup.
unwind
unwindДокумент, содержащий массив, можно разделить на несколько документов, и его синтаксис выглядит следующим образом:
{
$unwind:
{
path: <field path>,
includeArrayIndex: <string>,
preserveNullAndEmptyArrays: <boolean>
}
}
unwindНиже приведены поддерживаемые команды и соответствующие им описания:
| инструкция | тип | описывать |
|---|---|---|
path |
string | Указывает путь к полю поля массива, обязательно. |
includeArrayIndex |
string | Имя нового поля для хранения индекса массива элемента. |
preserveNullAndEmptyArrays |
boolean | По умолчанию, еслиpathзаnull, отсутствует это поле или пустой массив, документ не выводится. Вместо этого установите его наtrueдокумент будет выведен. |
Прежде чем приступить к обучению, нам необходимо подготовить следующие данные:
> db.shoes.save({_id: 1, brand: "Nick", sizes: [37, 38, 39]})
собиратьshoesсерединаsizesпредставляет собой массив с данными нескольких размеров. Предположим, вы хотите разделить этот документ на 3sizeДокумент с одним значением, соответствующий пример выглядит следующим образом:
> db.shoes.aggregate([{$unwind : "$sizes"}])
{ "_id" : 1, "brand" : "Nick", "sizes" : 37 }
{ "_id" : 1, "brand" : "Nick", "sizes" : 38 }
{ "_id" : 1, "brand" : "Nick", "sizes" : 39 }
Очевидно, что такой документ нам удобнее для обработки данных.preserveNullAndEmptyArraysПо умолчанию командаfalseЧто указано в документеpathПусто,nullили отсутствуетpath, документ будет проигнорирован. Предположим, что данные следующие:
> db.shoes2.insertMany([
{"_id": 1, "item": "ABC", "sizes": ["S", "M", "L"]},
{"_id": 2, "item": "EFG", "sizes": [ ]},
{"_id": 3, "item": "IJK", "sizes": "M"},
{"_id": 4, "item": "LMN" },
{"_id": 5, "item": "XYZ", "sizes": null}
])
Выполняем следующие команды:
> db.shoes2.aggregate([{$unwind: "$sizes"}])
Вы получите следующий вывод:
{ "_id" : 1, "item" : "ABC", "sizes" : "S" }
{ "_id" : 1, "item" : "ABC", "sizes" : "M" }
{ "_id" : 1, "item" : "ABC", "sizes" : "L" }
{ "_id" : 3, "item" : "IJK", "sizes" : "M" }
_idза2,4и5документация должна удовлетворитьpreserveNullAndEmptyArraysсостоянии, поэтому он не будет разделен.
ВышеупомянутоеunwindВведение в основное использование и функции , больше сunwindСоответствующие знания можно найти в официальной документацииunwind.
out
outроль агрегацииPipelineВозвращает результирующий документ и записывает его в указанную коллекцию. Чтобы быть осторожным,outДействие должно появиться вPipelineпоследний.outСинтаксис следующий:
{ $out: "<output-collection>" }
Подготовьте следующие данные:
> db.books.insertMany([
{ "_id" : 8751, "title" : "The Banquet", "author" : "Dante", "copies" : 2 },
{ "_id" : 8752, "title" : "Divine Comedy", "author" : "Dante", "copies" : 1 },
{ "_id" : 8645, "title" : "Eclogues", "author" : "Dante", "copies" : 2 },
{ "_id" : 7000, "title" : "The Odyssey", "author" : "Homer", "copies" : 10 },
{ "_id" : 7020, "title" : "Iliad", "author" : "Homer", "copies" : 10 }
])
предполагается собратьbooksРезультаты группировки сохраняются в файл с именемbooks_resultВ наборе соответствующие примеры следующие:
> db.books.aggregate([
... { $group : {_id: "$author", books: {$push: "$title"}}},
... { $out : "books_result" }
... ])
После выполнения команды MongoDB создастbooks_resultколлекции и сохраните результаты группировки в эту коллекцию. собиратьbooks_resultДокументация в следующем:
{ "_id" : "Homer", "books" : [ "The Odyssey", "Iliad" ] }
{ "_id" : "Dante", "books" : [ "The Banquet", "Divine Comedy", "Eclogues" ] }
ВышеупомянутоеoutВведение в основное использование и функции , больше сoutСоответствующие знания можно найти в официальной документацииout.
Map-Reduce
Map-reduce используется для сжатия больших объемов данных в полезные агрегированные результаты, и его синтаксис выглядит следующим образом:
db.runCommand(
{
mapReduce: <collection>,
map: <function>,
reduce: <function>,
finalize: <function>,
out: <output>,
query: <document>,
sort: <document>,
limit: <number>,
scope: <document>,
jsMode: <boolean>,
verbose: <boolean>,
bypassDocumentValidation: <boolean>,
collation: <document>,
writeConcern: <document>
}
)
в,db.runCommand({mapReduce: <collection>})также можно записать какdb.collection.mapReduce(). Соответствующее описание каждой команды выглядит следующим образом:
| инструкция | тип | описывать |
|---|---|---|
mapReduce |
collection | Название коллекции, обязательно. |
map |
function | Функции JavaScript требуются. |
reduce |
function | Требуется функция JavaScript. |
out |
string or document | Укажите требуемый результат вывода. |
query |
document | Оператор условия запроса. |
sort |
document | Сортировать документы. |
limit |
number | Укажите ввод дляmapМаксимальное количество документов. |
finalize |
function | ИсправлятьreduceВывод. |
scope |
document | Укажите глобальные переменные. |
jsMode |
boolean | Выполняется лиmapиreduceПреобразование промежуточных данных в формат BSON между функциями, по умолчаниюfalse. |
verbose |
boolean | Содержит ли результатtimingинформация, по умолчаниюfalse. |
bypassDocumentValidation |
boolean | Это разрешеноmapReduceОбход проверки документов во время работы, по умолчаниюfalse. |
collation |
document | Указывает, что использовать для операциисопоставление. |
writeConcern |
document | Укажите уровень записи, в противном случае используйте уровень по умолчанию. |
Простая картаУменьшить
ПростоmapReduceПримеры синтаксиса следучены следующим образом:
var mapFunction = function() { ... };
var reduceFunction = function(key, values) { ... };
db.runCommand(
... {
... ... mapReduce: <input-collection>,
... ... map: mapFunction,
... ... reduce: reduceFunction,
... ... out: { merge: <output-collection> },
... ... query: <query>
... })
mapКаждая функция отвечает за преобразование входного документа в ноль или более документов.mapСтруктура выглядит следующим образом:
function() {
...
emit(key, value);
}
emitРоль функции заключается в группировке, она принимает два параметра:
-
key: указывает поле, которое будет использоваться для группировки. -
value: Поле для агрегирования.
существуетmapможно использовать вthisКлючевое слово относится к текущему документу.reduceСтруктура выглядит следующим образом:
function(key, values) {
...
return result;
}
reduceВыполните конкретную операцию обработки данных, она получает два параметра:
-
key:иmapсерединаkeyТо же, поле группировки. -
values: По полю группировки будет одинаковоkeyпоместите значения в тот же массив,valuesэто объект, который содержит эти категориальные массивы.
outдля указания вывода результата,out: <collectionName>выведет результат в новую коллекцию или использует следующий синтаксис для вывода результата в существующую коллекцию:
out: { <action>: <collectionName>
[, db: <dbName>]
[, sharded: <boolean> ]
[, nonAtomic: <boolean> ] }
Обратите внимание, что еслиoutназначенныйcollectionуже существует, то он перезаписывает коллекцию. Прежде чем приступить к обучению, нам необходимо подготовить следующие данные:
> db.mprds.insertMany([
... {_id: 1, numb: 3, score: 9, team: "B"},
... {_id: 2, numb: 6, score: 9, team: "A"},
... {_id: 3, numb: 24, score: 9, team: "A"},
... {_id: 4, numb: 6, score: 8, team: "A"}
... ])
Затем определитеmapфункция,reduceфункцию и применить ее к коллекцииmrexampleначальство. Затем укажите место хранения для результата вывода, где результат вывода хранится в файле с именемmrexample_resultв коллекции.
> var func_map = function(){emit(this.numb, this.score);};
> var func_reduce = function(key, values){return Array.sum(values);};
> db.mprds.mapReduce(func_map, func_reduce, {query: {team: "A"}, out: "mprds_result"})
mapФункция указывает два ключа, которые должны быть включены в результат, и устанавливаетthis.classТот же документ выводится в тот же документ.reduceЗатем входящий список суммируется, а результат суммирования используется как результат в результате.value. После выполнения команды результат будет сохранен в коллекцииmprds_resultсередина. Просмотрите результаты с помощью следующей команды:
> db.mprds_result.find()
{ "_id" : 6, "value" : 17 }
{ "_id" : 24, "value" : 9 }
Документ_idкоторыйmapсерединаthis.numb,valueзаreduceВозвращаемое значение функции.
Рисунок ниже описываетmapReduceПолный процесс эксплуатации:
завершить обрезку
finallizeдля модификацииreduceВыходной результат, его синтаксический формат выглядит следующим образом:
function(key, reducedValue) {
...
return modifiedObject;
}
Он принимает два параметра:
key,иmapсерединаkeyТо же, поле группировки.
reducedValue,ОдинObecjt,ДаreduceВывод.
Выше мы представилиmapиreduce, и понять на простом примереmapReduceОсновной состав и использование. На самом деле, мы также можем написать более многофункциональныйreduceфункционировать, даже используяfinallizeИсправлятьreduceвыходной результат. следующееreduceфункция будет передана вvaluesвыполнять вычисления и реорганизацию, возвращаяreduceValОбъект:
> var func_reduce2 = function(key, values){
reduceVal = {team: key, score: values, total: Array.sum(values), count: values.length};
return reduceVal;
};
reduceValОбъект содержитteam,score,totalиcountчетыре свойства. но мы также хотим добавитьavgсвойства, то вы можетеfinallizeвыполнять в функцииavgРасчет стоимости иavgДобавление свойств работает:
> var func_finalize = function(key, values){
values.avg = values.total / values.count;
return values;
};
mapНе изменяйте, примените эти функции к коллекцииmprdsвыше соответствующий пример выглядит следующим образом:
> db.mprds.mapReduce(func_map, func_reduce2, {query: {team: "A"}, out: "mprds_result", finalize: func_finalize})
После выполнения команды результат будет сохранен в указанной коллекции. На данный момент коллекцияmprds_resultСодержание следующее:
{ "_id" : 6, "value" : { "team" : 6, "score" : [ 9, 8 ], "total" : 17, "count" : 2, "avg" : 8.5 } }
{ "_id" : 24, "value" : 9 }
Рисунок ниже описываетmapReduceПолный процесс эксплуатации:
finallizeсуществуетreduceпоследующее использование, тонкая настройкаreduceрезультат обработки. Похоже, садовник подстригает клумбу, поэтому людиfinallizeОбразно называется «обрезка».
Будьте осторожны:mapбудетkeyв документе с одинаковым значениемvalueВведенный в тот же объект, этот объект будет проходить черезreduceиfinallize. заkeyте документы, значение которых уникально, указанныеkeyиvalueбудут выведены напрямую.
простая агрегация
В дополнение к сложным операциям агрегации, таким как Aggregation Pipeline и Map-Reduce, MongoDB также поддерживает некоторые простые операции агрегации, такие какcount,groupиdistinctЖдать.
count
countИспользуется для подсчета количества документов в коллекции или представлении, возвращает документ, содержащий результат подсчета и статус. Его синтаксис следующий:
{
count: <collection or view>,
query: <document>,
limit: <integer>,
skip: <integer>,
hint: <hint>,
readConcern: <document>
}
countНиже приведены поддерживаемые команды и соответствующие им описания:
| инструкция | тип | описывать |
|---|---|---|
count |
string | Обязательное имя коллекции или представления для подсчета. |
query |
document | Оператор условия запроса. |
limit |
integer | Указывает максимальное количество возвращаемых совпадающих документов. |
skip |
integer | Указывает количество совпадающих документов, которые необходимо пропустить перед возвратом результатов. |
hint |
string or document | Укажите используемый индекс, указав имя индекса в виде строки или документа спецификации индекса. |
Предположим, вы хотите подсчитать коллекциюmprdsКоличество документов в соответствующих примерах следующее:
> db.runCommand({count: 'mprds'})
{ "n" : 4, "ok" : 1 }
Предположим, вы хотите подсчитать коллекциюmprdsсерединаnumbза6Количество документов, соответствующих примеров, следующее:
> db.runCommand({count: 'mprds', query: {numb: {$eq: 6}}})
{ "n" : 2, "ok" : 1 }
Указывает пропустить перед возвратом результатов1документы, соответствующие примеры следующие:
> db.runCommand({count: 'mprds', query: {numb: {$eq: 6}}, skip: 1})
{ "n" : 1, "ok" : 1 }
больше оcountЗнания можно найти в официальной документацииCount.
group
groupРоль состоит в том, чтобы сгруппировать документы в коллекции по указанному ключу и выполнить простую агрегатную функцию, аналогичную той, что используется в SQL.SELECT ... GROUP BYпохожий. Его синтаксис следующий:
{
group:
{
ns: <namespace>,
key: <key>,
$reduce: <reduce function>,
$keyf: <key function>,
cond: <query>,
finalize: <finalize function>
}
}
groupНиже приведены поддерживаемые команды и соответствующие им описания:
| инструкция | тип | описывать |
|---|---|---|
ns |
string | Требуется коллекция групп выполнения по операциям. |
key |
ducoment | Поле или поля для группировки, обязательные. |
$reduce |
function | Функция для выполнения операций агрегирования документов во время операций группировки. Функция принимает два аргумента: текущий документ и агрегированный результирующий документ для группы. Необходимые. |
initial |
document | Инициализировать документ результата агрегации, если требуется. |
$keyf |
function | альтернативаkey. Определяет функцию, используемую для создания "ключевого объекта" для использования в качестве ключа группировки.использовать $keyfвместоkeyСгруппировано по вычислительному полю вместо существующих полей документа. |
cond |
document | Критерии выбора для определения того, какие документы в коллекции следует обрабатывать. Если опущено, groupВсе документы коллекции обработаны. |
finalize |
function | Запустите перед возвратом результата, эта функция может изменить результирующий документ. |
Подготовьте следующие данные:
> db.sales.insertMany([
{_id: 1, orderDate: ISODate("2012-07-01T04:00:00Z"), shipDate: ISODate("2012-07-02T09:00:00Z"), attr: {name: "新款椰子鞋", price: 2999, size: 42, color: "香槟金"}},
{_id: 2, orderDate: ISODate("2012-07-03T05:20:00Z"), shipDate: ISODate("2012-07-04T09:00:00Z"), attr: {name: "高邦篮球鞋", price: 1999, size: 43, color: "狮王棕"}},
{_id: 3, orderDate: ISODate("2012-07-03T05:20:10Z"), shipDate: ISODate("2012-07-04T09:00:00Z"), attr: {name: "新款椰子鞋", price: 2999, size: 42, color: "香槟金"}},
{_id: 4, orderDate: ISODate("2012-07-05T15:11:33Z"), shipDate: ISODate("2012-07-06T09:00:00Z"), attr: {name: "极速跑鞋", price: 500, size: 43, color: "西湖蓝"}},
{_id: 5, orderDate: ISODate("2012-07-05T20:22:09Z"), shipDate: ISODate("2012-07-06T09:00:00Z"), attr: {name: "新款椰子鞋", price: 2999, size: 42, color: "香槟金"}},
{_id: 6, orderDate: ISODate("2012-07-05T22:35:20Z"), shipDate: ISODate("2012-07-06T09:00:00Z"), attr: {name: "透气网跑", price: 399, size: 38, color: "玫瑰红"}}
])
Предположим, вы хотите, чтобы коллекцииsalesДокументация вattr.nameГруппировка и ограничение количества документов, участвующих в группировкеshipDateбольше указанного времени. Соответствующий пример выглядит следующим образом:
> db.runCommand({
group:{
ns: 'sales',
key: {"attr.name": 1},
cond: {shipDate: {$gt: ISODate('2012-07-04T00:00:00Z')}},
$reduce: function(curr, result){},
initial: {}
}
})
После выполнения команды будет возвращен файл результатов. в,retvalВключить указанные поляattr.nameДанные,count- количество документов, участвующих в группировке,keysпредставляет количество групп,okПредставляет статус документа. В результате документ выглядит следующим образом:
{
"retval" : [
{
"attr.name" : "高邦篮球鞋"
},
{
"attr.name" : "新款椰子鞋"
},
{
"attr.name" : "极速跑鞋"
},
{
"attr.name" : "透气网跑"
}
],
"count" : NumberLong(5),
"keys" : NumberLong(4),
"ok" : 1
}
Указано в примере вышеkeyдаattr.name. Поскольку только 2 из 5 документов, участвующих в группировкеattr.nameОдинаково, результаты группировкиkeysза4, который представляет наборsalesДокументы в разделе разделены на 4 группы.
будетattr.nameзаменитьshipDateСмотрите, результаты будут такими, какие они есть. Соответствующий пример выглядит следующим образом:
> db.runCommand(
{
group:{
ns: 'sales',
key: {shipDate: 1},
cond: {shipDate: {$gt: ISODate('2012-07-04T00:00:00Z')}},
$reduce: function(curr, result){},
initial: {}
}
}
)
После выполнения команды возвращаются следующие результаты:
{
"retval" : [
{
"shipDate" : ISODate("2012-07-04T09:00:00Z")
},
{
"shipDate" : ISODate("2012-07-06T09:00:00Z")
}
],
"count" : NumberLong(5),
"keys" : NumberLong(2),
"ok" : 1
}
Поскольку несколько из 5 документов, участвующих в группировкеshipDateявляются дубликатами, поэтому в сгруппированном результатеkeysза2, который представляет наборsalesДокумент разделен на 2 группы.
В приведенном выше примере не используетсяreduce,initialиfinallize, далее мы продемонстрируем их использование и роль. Предположим, вы хотите подсчитать общий объем продаж одной и той же группы, тогда вы можетеreduceВыполнение определенной логики расчета в . Соответствующий пример выглядит следующим образом:
> db.runCommand(
{
group:{
ns: 'sales',
key: {shipDate: 1},
cond: {shipDate: {$gt: ISODate('2012-07-04T00:00:00Z')}},
$reduce: function(curr, result){
result.total += curr.attr.price;
},
initial: {total: 0}
}
}
)
После выполнения команды возвращаемый результат выглядит следующим образом:
{
"retval" : [
{
"shipDate" : ISODate("2012-07-04T09:00:00Z"),
"total" : 4998
},
{
"shipDate" : ISODate("2012-07-06T09:00:00Z"),
"total" : 3898
}
],
"count" : NumberLong(5),
"keys" : NumberLong(2),
"ok" : 1
}
Искусственная проверка, дата доставкиshipDateбольше, чем2012-07-04T09:00:00ZДокументация:
{ "_id" : 2, "orderDate" : ISODate("2012-07-03T05:20:00Z"), "shipDate" : ISODate("2012-07-04T09:00:00Z"), "attr" : { "name" : "高邦篮球鞋", "price" : 1999, "size" : 43, "color" : "狮王棕" } }
{ "_id" : 3, "orderDate" : ISODate("2012-07-03T05:20:10Z"), "shipDate" : ISODate("2012-07-04T09:00:00Z"), "attr" : { "name" : "新款椰子鞋", "price" : 2999, "size" : 42, "color" : "香槟金" } }
Общий объем продаж1999 + 2999 = 4998, что совпадает с возвращаемым результатом. Дата отправкиshipDateбольше, чем2012-07-06T09:00:00ZДокументация:
{ "_id" : 4, "orderDate" : ISODate("2012-07-05T15:11:33Z"), "shipDate" : ISODate("2012-07-06T09:00:00Z"), "attr" : { "name" : "极速跑鞋", "price" : 500, "size" : 43, "color" : "西湖蓝" } }
{ "_id" : 5, "orderDate" : ISODate("2012-07-05T20:22:09Z"), "shipDate" : ISODate("2012-07-06T09:00:00Z"), "attr" : { "name" : "新款椰子鞋", "price" : 2999, "size" : 42, "color" : "香槟金" } }
{ "_id" : 6, "orderDate" : ISODate("2012-07-05T22:35:20Z"), "shipDate" : ISODate("2012-07-06T09:00:00Z"), "attr" : { "name" : "透气网跑", "price" : 399, "size" : 38, "color" : "玫瑰红" } }
Общий объем продаж500 + 2999 + 399 = 3898, что совпадает с возвращаемым результатом.
Иногда может возникнуть необходимость подсчитать количество документов в каждой группе и рассчитать средние продажи.Соответствующие примеры приведены ниже:
> db.runCommand(
{
group:{
ns: 'sales',
key: {shipDate: 1},
cond: {shipDate: {$gt: ISODate('2012-07-04T00:00:00Z')}},
$reduce: function(curr, result){
result.total += curr.attr.price;
result.count ++;
},
initial: {total: 0, count: 0},
finalize: function(result){
result.avg = Math.round(result.total / result.count);
}
}
}
)
Приведенный выше пример изменился$reduceфункция для статистических целейcount. а затем добавилfinalizeЦель состоит в том, чтобы рассчитать средние продажи в группе. После выполнения команды верните следующую документацию:
{
"retval" : [
{
"shipDate" : ISODate("2012-07-04T09:00:00Z"),
"total" : 4998,
"count" : 2,
"avg" : 2499
},
{
"shipDate" : ISODate("2012-07-06T09:00:00Z"),
"total" : 3898,
"count" : 3,
"avg" : 1299
}
],
"count" : NumberLong(5),
"keys" : NumberLong(2),
"ok" : 1
}
ВышеупомянутоеgroupВведение в основное использование и функции , больше сgroupСоответствующие знания можно найти в официальной документацииgroup.
distinct
distinctРоль заключается в том, чтобы найти различные значения указанного поля в одной коллекции, и его синтаксис выглядит следующим образом:
{
distinct: "<collection>",
key: "<field>",
query: <query>,
readConcern: <read concern document>,
collation: <collation document>
}
distinctНиже приведены поддерживаемые команды и соответствующие им описания:
| инструкция | тип | описывать |
|---|---|---|
distinct |
string | Название коллекции, обязательно. |
key |
string | Указанное поле является обязательным. |
query |
document | Оператор условия запроса. |
readConcern |
document | |
collation |
document |
Подготовьте следующие данные:
> db.dress.insertMany([
... {_id: 1, "dept": "A", attr: {"款式": "立领", color: "red" }, sizes: ["S", "M" ]},
... {_id: 2, "dept": "A", attr: {"款式": "圆领", color: "blue" }, sizes: ["M", "L" ]},
... {_id: 3, "dept": "B", attr: {"款式": "圆领", color: "blue" }, sizes: "S" },
... {_id: 4, "dept": "A", attr: {"款式": "V领", color: "black" }, sizes: ["S" ] }
])
Предположим, вы хотите подсчитать коллекциюdressвсех документов вdeptРазличные значения поля, соответствующие примеры следующие:
> db.runCommand ( { distinct: "dress", key: "dept" } )
{ "values" : [ "A", "B" ], "ok" : 1 }
Или посмотрите на эти стили, соответствующие примеры приведены ниже.
> db.runCommand ( { distinct: "dress", key: "attr.款式" } )
{ "values" : [ "立领", "圆领", "V领" ], "ok" : 1 }
Даже если значение представляет собой массив,distinctС ним также можно обращаться правильно, и соответствующие примеры таковы:
> db.runCommand ( { distinct: "dress", key: "sizes" } )
{ "values" : [ "M", "S", "L" ], "ok" : 1 }
Сводка операций потокового агрегирования
Вышеизложенное является введением в операции потоковой агрегации в MongoDB в этой статье. Понятия агрегатов и конвейеров не являются общими, но их нетрудно понять. Если вы будете следовать примерам и практиковаться, я уверен, что вскоре вы сможете освоить операцию агрегирования.
Не можете видеть достаточно?
Помимо того, что я помог вам освоить операции потоковой агрегации, я также написал полный набор руководств по началу работы с MongoDB.После прочтения руководств вы получите:
- CRUD-операции и объекты Cursor для документов
- Освойте операции потоковой агрегации и легко справляйтесь с любыми потребностями в обработке данных
- Узнайте об эффективности запросов и оптимизации в MongoDB
- Научитесь улучшать удобство использования MongoDB
- Научитесь справляться со сбоями службы данных
- Понимание контроля доступа MongoDB
- Научитесь использовать модели данных, чтобы уменьшить избыточность данных и повысить эффективность
- Освойте методы резервного копирования и восстановления данных mongodump
Серия руководств по MongoDB подходит для людей
- 0 основных разработчиков, заинтересованных в MongoDB
- Разработчики, у которых есть определенный фундамент и которые хотят полностью понять MongoDB
Почему стоит выбрать этот набор руководств по MongoDB?
- Учебники MongoDB с аналогичным содержанием могут стоить сотни долларов на каждом шагу
- Официальная документация MongoDB неясна
- Другие статьи в Интернете недостаточно полны для формирования систематических знаний.
- Образец кода в чате можно скопировать и использовать напрямую, что удобно для практики
- В MongoDB много контента, и самообучающиеся не знают, что изучать
Это статья о быстром старте MongoDB, написанная для 0 студентов начального уровня. От документирования CRUD до операций потоковой агрегации; от планов выполнения, индексов, моделей данных до наборов реплик; от сегментирования, контроля доступа до резервного копирования и восстановления данных. Содержание почти 50 000 слов во всей статье охватывает большую часть знаний о MongoDB и полностью соответствует требованиям ежедневной разработки.
Прежде всего, этот набор учебных пособий стоит 9,9 юаня.
Вы можете добавить автора WeChat: DomFreez и пожаловаться на автора.
На данный момент приняли участие более 600 друзей