«Краткий учебник», чтобы легко освоить операции потоковой агрегации MongDB.

база данных MongoDB

Агрегация в информатике относится к процессу проверки контента, обработки и категоризации соответствующих данных и вывода результатов. Агрегация в 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Выполните конкретную операцию обработки данных, она получает два параметра:

  • keymapсередина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;
}

Он принимает два параметра:

keymapсередина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 друзей