Справочник от Автор24
Поделись лекцией за скидку на Автор24

Агрегация в MongoDB. Агрегатные выражения метода aggregation

  • 👀 544 просмотра
  • 📌 480 загрузок
Выбери формат для чтения
Загружаем конспект в формате pdf
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Конспект лекции по дисциплине «Агрегация в MongoDB. Агрегатные выражения метода aggregation» pdf
ЛЕКЦИЯ № 5 4.5 Агрегация 1 4.5.1 Агрегатные выражения 1 4.5.2 Операторы агрегации 17 6.1. Агрегация Агрегирование в общем смысле — это объединение нескольких элементов в единое целое. Агрегация в MongoDB — это процесс объединения при выборке результатов выполнения различных методов. Главная сложность в выборке данных – это работа с массивами, подколлекциями и поддокументами, содержащимися внутри каких-то отдельных элементов (документов и коллекций). Осуществлять поиск и выборку по ним можно и с помощью метода find, но детализировать, объединять, составлять по ним отчеты непосредственно при выборке нельзя. Метод aggregate позволяет осуществлять агрегацию данных вне зависимости от уровня вложенности. Агрегация данных осуществляется с помощью агрегатных выражений и операторов. Агрегатные выражения выполняют действия над документами и поддокументами коллекций/подколлекций. Агрегатные операторы выполняют операции над значениями полей документов/поддокументов. Помимо агрегатных операторов метод $aggregate поддерживает операторы метода find (табл. 8 – 10). 4.5.1 Агрегатные выражения В MongoDB реализован инструмент для выполнения цепочки операторов обработки документов коллекции — фреймворк агрегирования данных. На вход агрегирования поступают исходные документы коллекции, для которых последовательно выполняется цепочка операций. Документы на выходе одной операции поступают на вход следующей. Результат последней операции является результатом всей обработки. Конвейерную обработку выполняет ме1 тод aggregate. С помощью метода aggregate можно решать следующие задачи: 1) выполнение арифметических операций со значениями полей; 2) вычисление минимального значения поля; 3) вычисление максимально значения поля; 4) задание полю псевдонима; 5) конкатенация (соединение) значений всех строк заданного поля и другие операции со строками; 6) вывод данных из нескольких коллекций; 7) выполнение операций над датами; 8) группировка данных; 9) подсчет количества документов в коллекции/подколлекции; 10) выполнение операций с массивами. Метод aggregate нужно использовать для работы над значениями полей документов подколлекции. Обобщенный синтаксис метода aggregate имеет следующий вид: db.<Имя_коллекции>.aggregate ([<Агрегатное_выражение>,..]); <Агрегатное_выражение> — выполняемое действие и аргументы — атрибуты обрабатываемых входных документов, записанные в форме JSONобъекта: {<Оператор_агрегации>: [<Оператор_агрегации1: {Имя_поля1:Значение_поля1>}, <Оператор_агрегации2: {Имя_поля2:Значение_поля2>}…]} или для одиночного аргумента операция агрегации имеет вид: Оператор_агрегации:{Имя_поля:Значение_поля>} Примечание. При выполнении агрегации метод aggregate не может использоваться без агрегатных выражений. При выполнении агрегации необходимо указать хотя бы одно агрегатное выражение. Метод aggregate возвращает единственный документ с атрибутом result, 2 содержащий массив документов, элементы которого являются результатом агрегатной обработки исходных документов. Метод aggregate поддерживает использование в запросах выражений, аналогов некоторых встроенных функций SQL. Список доступных агрегатных выражений представлен в таблице 12. Таблица 12 Агрегатные выражения метода aggregation Имя Описание Синтаксис Описание синтаксиса агрегатного выражения Агрегатные выражения для добавления полей $addFields При выводе db.Имя_коллекции.aggreg Имя_поля – результата ate( [{$addFields: пользовательское имя выполнения {Имя_поля_1: поля, присваемое запроса {оператор_агрегации_1: вычисляемому полю; добавляет новые {"$Имя_поля_документа"} поля в },…,{Имя_поля_N: документы/подд {оператор_агрегации_N: окументы коллекции/подко оператор_агрегации – оператор, который осуществляет {"$Имя_поля_документа"} преобразование полей }}] ) ллекции БД и документов коллекции БД заменяет значения существующих полей $project При выводе db.Имя_коллекции.aggreg имя_агрегатного_выражен результата ate([{$project ия – название этапа выполнения {Имя_поля_1: агрегации; запроса {оператор_агрегации_1: Имя_поля – 3 изменяет {"$Имя_поля_документа"} пользовательское имя каждый },…,{Имя_поля_N: поля, присваемое документ, {оператор_агрегации_N: вычисляемому полю например, {"$Имя_поля_документа"} добавляя новые }}] ) поля или удаляя существующие поля Агрегатные выражения для группировки и объединения данных $sample Случайным db.Имя_коллекции.aggreg В параметр size образом ate([ { $sample: { size: заносится число выбирает указанное Количество_документов } выводимых документов } ]) количество документов из входных данных $group Выполняет db.Имя_коллекции.aggreg _id – содержит имя и группировку ate([{$group : {_id : значение поля, по документов по {Имя_поля:Значение_пол которому полю заданному я},{Имя_поля_1: осуществляется в запросе {оператор_агрегации_1: группировка, если в {"$Имя_поля_документа"} значении _id указано },…,{Имя_поля_N: null, то группировка не {оператор_агрегации_N: происходит, операторы {"$Имя_поля_документа"} агрегации применяются }}] ) ко всем документам коллекции БД $lookup Выполняет db.Имя_коллекции.aggreg $lookup выполняет объединение ate([{$lookup: {from: проверку на равенство 4 данных из нескольких коллекций "Имя_родительской_колл localField и foreignField из екции",localField: документов коллекции. "Поле_родительской_кол Если входной документ лекции",foreignField: не содержит localField, "Имя_дочерней_коллекци полю присваивается null и",as:"Поле_дочерней_ко ллекции"}}]) Агрегатные выражения для подсчета документов в коллекции/подколлекции $bucketAuto Выводит db.Имя_коллекции.aggreg groupBy – параметр, минимальное и ate([{$bucketAuto: содержащий поле, среди максимальное {groupBy: значений которого будут значение поля "$Имя_поля",buckets: найдены максимальное заданного в Целое_число}}]) и минимальное запросе, а также значения; количество buckets – параметр, документов позволяющий задать коллекции/подко количество диапазонов, ллекции в которых ищутся максимальное и минимальное значения поля $count Выполняет db.Имя_коллекции.aggreg Имя_вложенного_ подсчет ate([{$unwind:"$Имя_влож объекта – имя количества енного_объекта"}, подколлекции или документов во {$count:" массива, в котором вложенных Имя_вложенного_ осуществляется подсчет объектах, объекта "}]) документов; используется $count – возвращает совместно с массив элементов, 5 оператором указанных в запросе $unwid Агрегатные выражения для разделения данных по этапам агрегации $facet Позволяет db.Имя_коллекции.aggreg имя_агрегатного_выражен выполнить ate([{$facet:{Имя_поля_1: ия – название этапа несколько {имя_выражения_агрегац агрегации; агрегатных ии_1: Имя_поля – выражений в {"$Имя_поля_документа"} пользовательское имя рамках одного },…,{Имя_поля_N: поля, присваемое этапа {имя_выражения_агрегац вычисляемому полю ии: {"$Имя_поля_документа"} }}]) $match Фильтрует db.Имя_коллекции.aggreg В соответствие с документы ate([{$match : указанными {Имя_поля:Значение_пол Имя_поля:Значение_ я},{Имя_поля_1: поля документы {оператор_агрегации_1: фильтруются перед {"$Имя_поля_документа"} переходом на },…,{Имя_поля_N: следующий этап {оператор_агрегации_N: агрегации {"$Имя_поля_документа"} }}] ) $unwind Деконструкция db.Имя_коллекции.aggreg path используется для поля массива из входных ate( [ { $unwind: { path: указания пути к полю; "$полное_имя_поля",pres includeArrayIndex – имя документов. erveNullAndEmptyArrays: нового поля для Разбивает true|false } } хранения индекса массив на поля ]) массива элемента. Имя 6 документов в не может начинаться со формате ключ- знака доллара $. значение. Для preserveNullAndEmptyArrays каждого – если путь является входного недействительным, документа отсутствует или пустой выводит n массив, $unwid выдает документов, документ. Если false, где n – $unwid не выводит количество документ элементов массива и может быть нулем для пустого массива Агрегатные выражения позволяют выполнять сложные запросы благодаря их сочетанию. Пример синтаксиса взаимодействия агрегатных выражений: db.Имя_коллекции.aggregate([ <{$unwind:{<{filtration}>}}> <,{$match: { <{ filtration}>}}> <,{$project: { <{ filtration}>}}> <,{$group: {<{ filtration}>}}> <, { $sort: {Имя_поля: значение сортировки}}> …]) или db.runCommand( { aggregate: "Имя_коллекции", pipeline: [< {$project : {Имя_поля:"$Значение_поля"}}><, {$unwind:"$Имя_поля"}><, {$match: {"Имя_поля":Значение_поля, "Имя_поля":Значение_поля}}> ], cursor: { } } ) где 7 filtration – необязательный параметр, включающий в себя условия выборки; значение сортировки – 1 и -1 для сортировки по возрастанию и убыванию. Примечание. Порядок следования агрегатных выражений является произвольным. Рассмотренное взаимодействие выражений метода aggregate для примера представлено в следующем запросе: db.ABONENT.aggregate([{$match:{"STREET.id":3}},{$count:"ABONENT"}]) Рис. 4.92. Агрегация данных с помощью агрегатных выражений Выражение $match из всех документов коллекции ABONENT отбирает 8 документы, поле «STREET.id» которых равняется 3. Затем с помощью выражения $count подсчитывается количество документов, отобранных выражением $match. Количество абонентов, проживающих на улице с номером 3, можно также с помощью метода count и совместного использования методов count и find. db.ABONENT.count({"STREET.id":3}) db.ABONENT.find({"STREET.id":3}).count() Метод count и совместное использование методов count и find возвращают одинаковый результат. Отдельное использование метода count от метода find добавлено в версии MongoDB 3.6. Подсчет количества документов с помощью агрегации позволяет кроме количества документов вывести значения других полей документов. Агрегация позволяет строить цепочку для обработки данных, перечисляя выражения. Благодаря таким цепочкам выражений и операторов агрегация позволяет возвращать обработанные поддокументы и подколлекции после проведения вычислений над ними и значительно улучшать производительность обработки данных. Далее рассмотрены примеры последовательного построения агрегации с использованием нескольких агрегатных выражений. 1. Использование выражения $match Например, чтобы вывести информацию об абонентах, у которых нет номера телефона, нужно выполнить запрос: db.ABONENT.aggregate([{$match:{"Phone":{$eq:null}}},{$project:{Fio:1}}]) Результат выполнения запроса: /* 1 */ { "_id" : "136159", "Fio" : "Свирина З.А." 9 } /* 2 */ { "_id" : "136160", "Fio" : "Шмаков С.В." } В ходе выполнения запроса сначала из коллекции «ABONENT», с помощью выражения $match, отобраны все документы, у которых есть поле Phone не равно null. Затем выражение $project позволяет задать поля для вывода в результате выполнения запроса, выполняет горизонтальную проекцию. Например, чтобы вывести по каждой услуге значения оплат и номера месяцев, за которые они произведены, нужно выполнить запрос: db.SERVICES.aggregate([{$match:{"PAYSUMMA.PayMonth":{$ne:null}}},{$project: {"PAYSUMMA.PaySum":1,"PAYSUMMA.PayMonth":1}}]) или db.runCommand({aggregate:"SERVICES",pipeline:[{$match: {"PAYSUMMA.PayMonth":{$ne:null}}},{$project: {"PAYSUMMA.PaySum":1,"PAYSUMMA.PayMonth":1}}],cursor:{}}) Здесь для каждой услуги в начале с помощью выражения $match отбираются все документы, в которых указан месяц оплаты, а затем выражение $project выводит значения только указанных в нем полей. В результате выведены значения полей PaySum и PayMonth документов подколлекции PAYSUMMA коллекции SERVICES (рис. 4.93). 10 Рис. 4.93. Фрагмент результата выполнения запроса 2. Использование выражения $unwind Выражение $unwind используется для развертывания подколлекции. После проведения развертывания, можно обращаться к документам подколлекции и выполнять операции над ними. До проведения развертывания все действия относятся к документам коллекции. Например, чтобы подсчитать количество заявок, нужно выполнить запрос: db.DISREPAIR.aggregate([{$unwind:"$REQUEST"},{$count:"REQUEST"}]) Выражение $unwind разворачивает подколлекцию REQUEST, затем выражение $count подсчитывает количество документов в подколлекции. В результате выполнения запроса выведено количество документов подколлекции REQUEST коллекции DISREPAIR: 21 3. Совместное использование выражений $match и $unwind Например, чтобы вывести названия неисправностей заявок с номерами меньше 8 и номера слесарей, которым назначены найденные заявки, с номером больше 2, нужно выполнить запрос: 11 db.DISREPAIR.aggregate([{$unwind:"$REQUEST"},{$match:{"REQUEST._id": {$lt:8}}},{$match:{"REQUEST.EXECUTOR.id":{$gt:2}}}]) Выражение $unwind разворачивает подколлекцию REQUEST, затем выражение $match отбирает все документы, в которых _id документов подколлекции REQUEST меньше 8 и поле «EXECUTOR.id» имеет значение больше 2. В результате выполнения запроса выведены документы подколлекции REQUEST со значением поля _id меньше 8 и документы коллекции EXECUTOR со значением _id больше 2. /* 1 */ { "_id" : 1, "FailureNM" : "Засорилась водогрейная колонка","REQUEST" : {"_id" : 2, "ABONENT" :{"ref":"ABONENT","id": "115705"},"IncomingDate" : ISODate("201408-06T21:00:00.000Z"),"ExecutionDate" : ISODate("2014-08- 11T21:00:00.000Z"),"Executed" : true, "EXECUTOR" : {"ref" : "EXECUTOR","id" : 3} } } /* 2 */ {"_id" : 1, "FailureNM" : "Засорилась водогрейная колонка","REQUEST" : {"_id" : 5, "ABONENT" :{"ref":"ABONENT","id": "080270"},"IncomingDate" : ISODate("201412-30T21:00:00.000Z"),"Executed" : false, "EXECUTOR" : {"ref" : "EXECUTOR","id" : 4}} } /* 3 */ {"_id" : 2, FailureNM" : "Не горит АГВ","REQUEST" : {"_id" : 7, "ABONENT" : {"ref":"ABONENT","id": "080047"},"IncomingDate" 19T21:00:00.000Z"),"ExecutionDate" : : ISODate("2015-10ISODate("2015-10- 23T21:00:00.000Z"),"Executed" : true, "EXECUTOR" : {"ref" : "EXECUTOR","id" : 3}} } 4. Использование выражения $project Если требуется выбрать определенные документы из коллекции, то для указания значений или имен полей, которые нужно выбрать, используется 12 агрегатное выражение $project. Если для каждой услуги требуется вывести ее номер и номер лицевого счета каждого факта оплаты, то это можно получить так: db.SERVICES.aggregate([{$project:{"PAYSUMMA.ABONENT":1}}]) В результате выполнения запроса выведены только значения полей «PAYSUMMA.ABONENT.id» и «PAYSUMMA.ABONENT.ref» документов подколлекции «PAYSUMMA» коллекции «SERVICES» (рис. 4.94). Рис. 4.94. Результат выполнения запроса с выражением $project Для выбора неисправностей, заявки по которым были зарегистрированы позднее 1 октября 2016 года, нужно выполнить запрос: db.DISREPAIR.aggregate([{$project:{_id:1,FailureNM:1,Date:{$gt: [ "$REQUEST.IncomingDate", "01.10.2016" ] }} }]) В результате выполнения запроса выражение $project выводит значения полей _id и FailureNM, а также поле с псевдонимом Date, содержащее 13 результат сравнения даты принятия заявки и даты 1 октября 2016. Если дата выполнения всех заявок по неисправности больше 1 октября 2016, то выводится значение true, иначе false. В результате выполнения запроса в поле Date выведется значение true, если дата принятия заявки больше указанной в запросе, и false, если меньше (рис. 4.95). Рис. 4.95. Результат выполнения запроса 5. Использование агрегатного выражения $group Например, чтобы вывести по каждой услуге суммы значений оплат, надо выполнить запрос (результат на рис. 4.96): db.SERVICES.aggregate([ {$unwind : "$PAYSUMMA"},{$group:{ _id:"$_id" , PaySum: {$sum: "$PAYSUMMA.PaySum"}}}]) Рис. 4.96. Взаимодействие операторов метода aggregation 6. Использование агрегатного выражения $sort 14 Например, для вывода по каждой услуге сумм значений оплат, отсортированных по убыванию, нужно выполнить запрос (результат на рис. 4.97): db.SERVICES.aggregate([{$unwind:"$PAYSUMMA"}, {$group : { _id:"$ServiceNM",PaySum: {$sum: "$PAYSUMMA.PaySum"}}},{$sort : {PaySum : -1}} ] ) Результат выполнения запроса: { "_id" : "Водоснабжение", "PaySum" : 6229.21 } { "_id" : "Теплоснабжение", "PaySum" : 3977.55 } { "_id" : "Электроснабжение", "PaySum" : 1275.1 } { "_id" : "Газоснабжение", "PaySum" : 926.92 } или db.runCommand({aggregate:"SERVICES",pipeline:[{$unwind:"$PAYSUMMA"}, {$group : { _id:"$ServiceNM" ,PaySum: {$sum: "$PAYSUMMA.PaySum"}}},{$sort : {PaySum : -1}} ], cursor: { }} ) 15 Рис. 4.97. Результат выполнения запроса 7. Использование агрегатного выражения $lookup Агрегация в MongoDB также используется для объединения данных при выводе результата запроса из двух коллекций. Агрегатное выражение $lookup метода aggregate используется для объединения данных из нескольких коллекций. Аналогом этого метода является LEFT JOIN (левое соединение) в реляционных СУБД. Например, чтобы всю вывести информацию обо всех абонентах вместе с названиями улиц, на которых они проживают, нужно выполнить запрос: db.ABONENT.aggregate([{ $lookup: { from: "STREET", localField: "STREET.id", foreignField: "_id", as: "STREET.id"}}]) или db.runCommand({ aggregate:"ABONENT", pipeline:[ {$lookup:{ 16 from:"STREET", localField:"STREET.id", foreignField:"_id", as:"STREET.id"}} ], cursor:{} } ) В результате выполнения запроса в поле «STREET.id» выведены данные из коллекции STREET, а именно номер улицы и ее название (рис. 4.98). Рис. 4.98. Результат выполнения выражения $lookup Например, чтобы найти всю информацию об абонентах с лицевыми счетами 015527, 136159 и о поданных ими заявках, применяется запрос: db.DISREPAIR.aggregate({$match: {"REQUEST.ABONENT.id":"015527","REQUEST.ABONENT.id":"136159"}},{$lookup: {from:"ABONENT",localField:"REQUEST.ABONENT.id", foreignField:"_id",as:"ABONENTS"}}) При выводе результата запроса в коллекцию «DISREPAIR» добавлена 17 подколлекция «ABONENTS», содержащая документы коллекции «ABONENT» со значением поля _id равным 015527 и 136159 (рис. 4.99). Рис. 4.99. Результат выполнения запроса 4.5.2 Операторы агрегации Метод aggregate помимо операторов, доступных для метода find, поддерживает следующие пять видов операторов агрегации: 1) скалярные операторы; 2) арифметические операторы; 3) операторы для массивов; 4) операторы управления документами и коллекциями; 5) условные операторы. Скалярные операторы (их еще называют однострочными) обрабатывают одиночное значение и возвращают также одно значение. Скалярные операторы бывают следующих категорий: 1) строковые операторы, которые выполняют определенные действия над строками и возвращают строковые или числовые значения. В MongoDB такие операторы представлены операторами: $concat, $split, $indexOfBytes, $indexOfCP, $strLenBytes, $substr, $substrBytes, $substrCP, $strcasecmp, $toLower, $toUpper; 18 2) числовые операторы, которые возвращают числовые значения на основании заданных в аргументе значений того же типа. В MongoDB такие операторы представлены операторами: $abs, $add, $ceil, $divide, $exp, $floor, $ln, $log, $log10, $mod, $multiply, $pow, $trunc, $sqrt, $subtract; 3) операторы времени и даты, которые выполняют различные действия над входными значениями времени и даты и возвращают строковое, числовое значения или значение в формате даты и времени. В MongoDB такие операторы представлены операторами: $dayOfYear, $dayOfMonth, $dayOfWeek, $year, $month, $week, $hour, $minute, $second, $millisecond; 4) арифметические операторы, которые используются для получения обобщающих значений. Они, в отличие от скалярных функций, оперируют значениями полей множества документов. К агрегатным операторам относятся такие операторы, как: $sum (итог), $max и $min (наибольшее и наименьшее значения) и $avg (среднее значение). Операторы для массивов используются при обработке значений, заданных в массиве элементов. В MongoDB такие операторы представлены операторами: $arrayElemAt, $arrayToObject, $concatArrays, $filter и другими. Операторы массивов в чем-то похожи на строковые операторы, например, $concatArrays и $concat, однако $concatArrays объединяет элементы не из множества значений строк, а из элементов, заданных в массиве. В качестве операторов управления документами и коллекциями используются операторы: $collStats, $project, $match и другие. Возвращаемый этими операторами результат меняется в зависимости от значения, которое обрабатывается оператором. Условные операторы предназначены для статистического анализа данных в готовой выборке. Это довольно мощный и удобный инструмент, который присутствует во многих СУРаБД. В MongoDB такие операторы представлены операторами: $cond, $ifNull, $switch и другими. 19 В версии СУРаБД 4.0.0 добавлены новые агрегатные операторы для преобразования типов данных на стороне СУБД: универсальный оператор $convert для конвертации в любой указанный тип и привязанные к конкретным типам операторы $toBool, $toDate, $toDecimal, $toDouble, $toInt, $toLong, $toObjectId и $toString. Строковые операторы Строковые операторы (таблица 13) используют в качестве аргумента строку символов, а в качестве результата возвращают также символьную строку или числовое значение. Таблица 13 Строковые операторы Выражение Описание Синтаксис Описание синтаксиса $concat Конкатенация db.Имя_коллекции. В результате строк, операция aggregate([ { $project: запроса при выводе склеивания {Новое_имя_поля: документов строк в одну { $concat: [ "$Имя_поля", коллекции поля "выражение_пользователя", будут соединены в "$Имя_поля_2" ] } } } ]) одно поле, а между ними будет располагаться соединительная строка, заданная пользователем $split Разделяет db.Имя_коллекции. В результате строку на aggregate([ выполнения подстроки. { $project : { Новое_имя_поля: запроса значение Возвращает { $split: ["$Имя_поля", ", "] }} } ]) поля будет 20 массив разделено на подстрок. Если подстроки, по разделитель не указанному найден в разделителю, в строке, примере возвращает разделителем массив, является запятая содержащий исходную строку $indexOfBytes Выполняет db.Имя_коллекции. Данная операция поиск aggregate( использует подстроки и [{$project:{Новое_имя_поля: оператор возвращает { $indexOfBytes: $indexOfBytes для UTF-8 код [ "$Имя_поля", извлечения вхождения "Значение_поля" ] }}}]) индексов, по подстроки. которым находится Если подстрока указанное значение не найдена, поля возвращает -1 $indexOfCP Выполняет db.Имя_коллекции. Операция поиск начала aggregate([ использует подстроки и { $project: { оператор возвращает Новое_имя_поля: $indexOfCP для UTF-8 код {$indexOfCP: [ "$Имя_поля", возврата индекса первого "Значение_поля" ]} начальной точки, в вхождения }}]) которой значение подстроки. поля находится в 21 $toUpper Если подстрока значении поля не найдена, документа с возвращает -1 указанным именем Преобразует db.Имя_коллекции. В результате строку в aggregate([ выполнения верхний {$project:{ запроса все регистр. Имя_поля: { $toUpper: значения Принимает "$Имя_поля" }}}}]) указанного поля одно будут написаны выражение заглавными аргумента. буквами Применяется только к латинским буквам $toLower Преобразует db.Имя_коллекции. В результате строку в aggregate([ выполнения нижний {$project:{ запроса все регистр. Имя_поля: { $toLower: значения Принимает "$Имя_поля" }}}}]) указанного поля одно документов выражение коллекции БД аргумента. будут написаны Применяется строчными только к буквами латинским буквам $strLenBytes Возвращает db.Имя_коллекции. Данная операция 22 число aggregate([{ использует закодированны $project: {" ": 1, оператор х байтов UTF-8 "Новое_имя_поля": $strLenBytes для в строке {$strLenBytes:"$Имя_ вычисления длины поля" }}}]) каждого имени поля документа $substr Возвращает db.Имя_коллекции. Если ($substrBytes строку или aggregate( [ является $substrCP, подстроку. {$project: {_id: 1, отрицательным используются Если длина Имя_поля: { $substr: [ , числом, $substr для вывода указывается , ] }}]) возвращает пустую строки по отрицательным строку "". заданным значением, то Если байтам и возвращается является кодировке пустая строка. отрицательным US-ASCII) Под каждую числом, $substr букву возвращает кириллицы подстроку, с отводится по 2 указанной позиции символа длины длины строки и включает в себя остаток строки $strcasecmp Сравнивает db.Имя_коллекции.aggregate([{ В результате строки и $project:{Имя _поля: выполнения возвращает: { $strcasecmp: [ "$Имя_поля", запроса будут 1, если первая "Значение_поля" ] } } выведены все строка больше }]) документы второй строки; коллекции со 23 0, если две значением строки равны; указанного имени -1, если первая поля (1, 0, -1) строка меньше второй строки $ltrim Удаляет пробе- db.Имя_коллекции.aggregate([{ лы или указан- Если в начале $ltrim: ные символы из {input:string, chars:string}}}]) строки стоит пробел в параметре char он также начала строки $rtrim Удаляет пробе- db.Имя_коллекции.aggregate([{ лы или указан- $rtrim: ные символы из {input:string, chars:string}}}]) указывается конца строки Далее представлены примеры выполнения каждого из операторов обработки строк. Например, для вывода номеров услуг и первых трех символов их названия (результат на рис. 4.100), можно использовать запрос: db.SERVICES.aggregate( [{$project: {ServiceNM: {$substr: [ "$ServiceNM", 0, 6]}}}]) Рис. 100. Результат выполнения запроса Оператор $substr позволяет вывести часть слова или фразы. В рассмотренном выше примере выводится первые три буквы названия услуги, поскольку каждая русская буква занимает два символа длины строки. Например, если требуется вывести лицевой счет и номер телефона абонента с добавлением константы «имеет телефон» и задать псевдоним поля 24 «Информация о телефоне», то используется запрос: db.ABONENT.aggregate([{ $project:{ "Информация о телефоне":{$concat:[ "$_id", " имеет телефон ", "$Phone" ]}}}]) В результате выполнения запроса для каждого документа коллекции ABONENT выведено поле «Информация о телефоне», в котором выведена строковая константа, заданная пользователем и значение поля Phone (рис. 101). Рис. 101. Результат выполнения запроса с оператором $concat Для вывода номеров лицевых счетов зарегистрированных абонентов с добавлением строковой константы «Абонент зарегистрирован под лицевым счетом» с заданным псевдонимом поля «Account» используется запрос (результат на рис. 4.102): db.ABONENT.aggregate([{ $project:{Account:{$concat:[ " Абонент зарегистрирован под лицевым счетом ", "$_id" ]}, _id:0}}]) 25 Рис. 4.102. Добавление строкой константы Например, для вывода лицевых счетов абонентов и первых двух цифр их номера лицевого счета (результат на рис. 4.103) нужно использовать запрос: db.ABONENT.aggregate( [{$project: {Phone: {$substr: [ "$Phone", 0, 2]}}}]) Рис. 4.103. Результат выполнения запроса с оператором $substr Числовые операторы В основном числовые операторы (таблица 14) представляют собой 26 различные арифметические операции, в результате которых возвращается значение такого же типа, как исходные значения в запросе. Таблица 14 Арифметические операторы Выражение Описание Синтаксис Описание синтаксиса $sum Суммирует значения db.Имя_коллекции. Имя_поля – имя поля (SUM) поля, указанного в aggregate([{$project:{ документов запросе Имя_поля : {$sum : коллекции БД, "$Имя_поля"}}}]) значения которых суммируются $min Получает минимум (MIN) из всех значений db.Имя_коллекции. aggregate([{$project:{ коллекции БД, среди указанного в запросе Имя_поля : {$min : "$Имя_поля"}}}]) поля документов коллекции $max (MAX) значений которого находятся минимальное Получает максимум db.Имя_коллекции. Имя_поля – имя поля aggregate([{$project:{ коллекции, среди указанного в запросе Имя_поля : {$max : значений которого из всех значений поля документов "$Имя_поля"}}}]) коллекции $abs Имя_поля – имя поля находится максимальное Вычисляет абсолютное { $abs: – любое значен-ие всех } числовое значение { $exp: } – целое заданных значений из всех документов в коллекции $exp Возвращает экспоненту числа числовое значение 27 $trunc Выводит целую часть { $trunc: } числового значения – любое числовое значение поля $ceil Возвращает { $ceil: Аргумент возвращает наименьшее целое } null, если значение число, большее или отсутствует, иначе равное указанному $ceil возвращает числу, округляя его ближайшее целое к указанному в запросе значению поля $divide Выражение { $divide: [ Первый аргумент – используется для expression_1, это делимое, второй выполнения expression_2] } аргумент – делитель, операции деления первое значение, между указанными делится на второе значениями полей или числами $ln $floor Вычисляет { $ln: }| $log: Math.E – натуральный [ , Math.E ] представление логарифм значения JavaScript для числа поля документа e (Эйлера) Возвращает { $floor: } Если аргумент наибольшее целое указывает на число, меньшее или значение null или равное указанному указывает на поле, числу, округляя в которое отсутствует, меньшую сторону $floor возвращает значение null $log Вычисляет { $log: [ , – 28 логарифм значения $log10 ] } неотрицательное поля документа число. коллекции по – заданному положительное число основанию больше 1 Рассчитывает { $log10: }| десятичный логарифм $log: [ , 10 ] значения поля – неотрицательное число документа коллекции БД $multiply Оператор умножает { $multiply: Аргументы могут значение поля на [ ,…, иметь любое число или на ]} числовое значение { $mod: Первый аргумент – значение другого поля $mod Оператор делит значение поля документа на число [,…, это дивиденд, второй ]} аргумент – делитель, или на значение первый аргумент, другого поля делится на второй аргумент $pow Вычисляет { $pow: [ , – числовое дисперсию значения ] } значение; – целое поля коллекции БД число $sqrt Вычисляет { $sqrt: Аргумент – квадратный корень } неотрицательное значения поля число коллекции БД 29 $subtract Выполняет операцию { $subtract: Второй аргумент вычитания между [expression_1, вычитается из двумя значениями expression_2]} первого аргумента. полей, числами или Аргументы могут датами быть числами и/или датой. Далее представлены примеры использования арифметических операторов. Например, чтобы найти для каждой услуги максимальное и минимальное значения оплаты (результат на рис. 4.104), можно выполнить следующий запрос: db.SERVICES.aggregate([{$project: {PaySumMax: { $max:"$PAYSUMMA.PaySum"}, PaySumMin: { $min: "$PAYSUMMA.PaySum" }}}]) Рис. 4.104. Результат выполнения запроса с операторами max и min Расчет сумм всех оплат и начислений по каждой услуге можно произвести таким образом: db.SERVICES.aggregate([{$project: {PaySum: { $sum: "$PAYSUMMA.PaySum"}, NachislSum: { $sum: "$NACHISLSUMMA.NachislSum" }}}]) или db.runCommand({aggregate:"SERVICES",pipeline:[ {$project:{PaySum:{$sum:"$PAYSUMMA.PaySum"},NachislSum: {$sum:"$NACHISLSUMMA.NachislSum" }}}],cursor: { }} ) Результат выполнения запроса представлен на рис. 4.105 – рис. 4.106. 30 Рис. 4.105. Результат выполнения запроса или 31 Рис. 4.106 Результат выполнения запроса runCommand Здесь происходит суммирование всех оплат и начислений для каждой услуги. Например, чтобы вывести результат вычисления интервала времени, затраченного на выполнение каждой заявки слесарем под номером 3, надо выполнить запрос: db.DISREPAIR.aggregate([{$unwind:"$REQUEST"},{$match: {"REQUEST.EXECUTOR.id":3}},{$project: {EXECUTOR:"$REQUEST.EXECUTOR",Time:{$subtract: ["$REQUEST.ExecutionDate","$REQUEST.IncomingDate"]} } }]) В результате выполнения запроса будет вычислена и выведена разница между датами принятия и выполнения заявки в миллисекундах: {"_id":1,"EXECUTOR":{"ref":"EXECUTOR","id":3}, "Time":NumberLong(432000000)} {"_id":12,"EXECUTOR":{"ref" : "EXECUTOR","id" : 3}, 32 "Time" : NumberLong(172800000)} {"_id":2,"EXECUTOR" : {"ref" : "EXECUTOR","id" : 3}, "Time" : NumberLong(345600000)} {"_id" : 2, "EXECUTOR" : {"ref" : "EXECUTOR","id" : 3 }, "Time" : NumberLong(0)} Или для расчета в днях: db.DISREPAIR.aggregate([{$unwind:"$REQUEST"},{$match: {"REQUEST.EXECUTOR.id":3}},{$project:{EXECUTOR:"$REQUEST.EXECUTOR",Time: {$divide:[{$subtract:["$REQUEST.ExecutionDate","$REQUEST.IncomingDate"]},86400000]} } }]) С помощью выражения $group можно сгруппировать документы по определенному выражению и вывести на следующий этап документ по каждой отдельной группировке. Например, если необходимо вычислить средние значения начислений за каждую услугу (результат на рис. 4.107 – рис. 4.108), то нужно выполнить запрос: db.SERVICES.aggregate([{ $group : {_id: { $avg: "$NACHISLSUMMA.NachislSum" }}}]) или db.runCommand( {aggregate: "SERVICES",pipeline: [{ $group : {_id: { $avg: "$NACHISLSUMMA.NachislSum" }}} ], cursor: { }} ) Рис. 4.107. Результат выполнения запроса с оператором $group или 33 Рис. 4.108. Результат выполнения запроса runCommand Например, если требуется узнать количество дней, затраченное на выполнение всех заявок каждым исполнителем (результат на рис. 4.109), то используется запрос: db.DISREPAIR.aggregate([{$unwind:"$REQUEST"},{$match:{"REQUEST.EXECUTOR.id": {$ne:null}}},{$group:{_id:"$REQUEST.EXECUTOR.id",Sum:{$sum:{$subtract: ["$REQUEST.ExecutionDate","$REQUEST.IncomingDate"]}}}},{$project: {Hours: {$divide: [ "$Sum", 86400000] }}}]) Рис. 4.109. Результат выполнения запроса В результате выполнения запроса выведены _id исполнителей заявок и количество дней, которое было затрачено на выполнение всех заявок. Значение null выводится, поскольку одной заявке не назначен исполнитель. Операторы даты и времени Операторы даты и времени (таблица 15) выполняют различные действия над входными значениями времени и даты строковое, значения или значение в формате числовое даты и и возвращают времени. 34 Таблица 15 Операторы даты и времени Выражение Описание $dayOfYear Возвращает день года для даты как число от 1 до 366 (високосный год) $dayOfMonth Возвращает день месяца для даты как число от 1 до 31 $dayOfWeek Возвращает день недели для даты в виде числа от 1 (воскресенье) до 7 (суббота) $year Возвращает год для даты в виде числа $month Возвращает месяц для даты в виде числа от 1 (январь) до 12 (декабрь) $week Возвращает номер недели как число между 0 (частичная неделя, предшествующая первому воскресению года) и 53 $hour Возвращает час для даты как число между 0 и 23 $minute Возвращает минуты для даты число от 0 до 59 $second Возвращает секунды для даты число от 0 до 60 $millisecond Возвращает миллисекунды для даты число от 0 до 999 Следует отметить, что даты в запросе указываются в одном из форматов, поддерживаемых MongoDB. Например, чтобы вывести название неисправности с номером 3 и даты выполнения заявок по ее устранению, нужно выполнить запрос: db.DISREPAIR.aggregate([{$match:{_id:3}},{$unwind : "$REQUEST"}, {$project:{FailureNM:"$FailureNM","REQUEST":"$REQUEST.ExecutionDate", _id:0}}) или 35 db.runCommand({aggregate:"DISREPAIR",pipeline:[{$match:{_id:3}}, {$unwind:"$REQUEST"},{$project: {FailureNM:"$FailureNM","REQUEST":"$REQUEST.ExecutionDate",_id:0}}],cursor: { }} ) В результате выполнения запроса будет выведено название неисправности с идентификатором 3 и даты выполнения заявок по ее устранению: /* 1 */ { "FailureNM" : "Течет из водогрейной колонки" } /* 2 */ { "FailureNM" : "Течет из водогрейной колонки", "REQUEST" : ISODate("2018-02-03T21:00:00.000Z") } Например, чтобы получить подробную информацию о датах выполнения заявок, нужно выполнить запрос: db.DISREPAIR.aggregate( [{$unwind:"$REQUEST"}, { $project: { year: { $year: "$REQUEST.ExecutionDate" }, month: { $month: "$REQUEST.ExecutionDate" }, day: { $dayOfMonth: "$REQUEST.ExecutionDate" }, hour: { $hour: "$REQUEST.ExecutionDate" }, minutes: { $minute: "$REQUEST.ExecutionDate" }, seconds: { $second: "$REQUEST.ExecutionDate" }, 36 milliseconds: { $millisecond: "$REQUEST.ExecutionDate" }, dayOfYear: { $dayOfYear: "$REQUEST.ExecutionDate" }, dayOfWeek: { $dayOfWeek: "$REQUEST.ExecutionDate" }, week: { $week: "$REQUEST.ExecutionDate" } } } ] ) Фрагмент результата выполнения запроса: /* 1 */ { "_id" : 1, "year" : 2017, "month" : 1, "day" : 19, "hour" : 21, "minutes" : 0, "seconds" : 0, "milliseconds" : 0, "dayOfYear" : 19, "dayOfWeek" : 5, "week" : 3 } /* 2 */ { "_id" : 1, "year" : 2016, "month" : 9, "day" : 11, 37 "hour" : 21, "minutes" : 0, "seconds" : 0, "milliseconds" : 0, "dayOfYear" : 255, "dayOfWeek" : 1, "week" : 37 } Здесь для значения поля Date документа указанной коллекции будет выведено: год, месяц, число, час, минуты, секунды и миллисекунды выполнения заявки, а также порядковый номер дня выполнения заявки в году, номер дня недели выполнения заявки (начиная от воскресенья 1 и до субботы 7) и порядковый номер недели года. Например, чтобы получить подробную информацию о датах подключения к службе MongoDB, упорядоченных по убыванию, нужно выполнить запрос: db.startup_log.aggregate( [ { $project: { year: { $year: "$startTime" }, month: { $month: "$startTime" }, day: { $dayOfMonth: "$startTime" }, hour: { $hour: "$startTime" }, minutes: { $minute: "$startTime" }, seconds: { $second: "$startTime" }, milliseconds: { $millisecond: "$startTime" }, dayOfYear: { $dayOfYear: "$startTime" }, dayOfWeek: { $dayOfWeek: "$startTime" }, 38 week: { $week: "$startTime" } } }, { $sort:{_id:-1}} ] ) Например, чтобы отобразить номер месяца поступления заявок для неисправности с идентификатором 2, нужно выполнить запрос: db.DISREPAIR.aggregate([{$unwind : "$REQUEST"},{$match: { _id: 2 }},{$project: {month: { $month: "$REQUEST.IncomingDate"}}}]) В результате выполнения запроса выведены все номера месяцев поступления заявок по неисправности с номером 2: {"_id" : 2,"month" : 10} {"_id" : 2,"month" : 8} {"_id" : 2, "month" : 10} {"_id" : 2,"month" : 9} Операторы для работы с массивами Операторы для работы с массивами (таблица 16) используются для обработки значений, заданных в массиве элементов. Таблица 16 Операторы массивов Выражение Описание Синтаксис Описание синтаксиса $setIntersec Выводит db.Имя_массива. Элемент_массива – tion совпавшие aggregate([{$project: элементы массива элементы {Имя_массива: коллекции БД, которые сравниваемых {$setIntersection: сравниваются друг с массивов [ "$Элемент_массива", другом "$Элемент_массива"] }}}]) 39 $setEquals Сравнивает db.Имя_коллекции. элементы_массива1– массивы и aggregate([{$project: элементы массива выводит true, {$setEquals: коллекции БД, которые если они имеют [ "Элемент_массива_1", похожие "…","Элемент_массива_N элементы, "], ["Элемент_массива_2 иначе false "…", сравниваются с элементами_массива2 "Элемент_массива_M"] ]}}] ) $arrayElemA Возвращает { $arrayElemAt: [ , – массив; t элемент по ] } элемент – целое указанному число, если индексу положительное массива значение, то $arrayElemAt возвращает элемент в позиции idx, считая с начала массива, иначе – считая от конца массива. Если индекс превышает границы массива, $arrayElemAt не возвращает никакого результата $concat Объединяет {$concatArrays: – массивы строк Arrays массивы [ ,..., или чисел ]} $filter Выбирает { $filter: { input: , as: as – имя переменной, 40 подмножество , cond: представляющей массива, чтобы } } каждый отдельный вернуть массив элемент входного только с массива. Если имя не элементами, указано, по умолчанию соответствую используется имя щими условию переменной. фильтра cond – выражение, задающее условие для включения элемента в выходной массив. Выражение ссылается на каждый элемент входного массива с помощью переменной, указанной в as $isArray Определяет, { $isArray: Expression (выражение) является ли [ ] } может включать имена операнд полей и системные массивом переменные, объекты, массивы и операторы выражений. Возвращает логическое выражение $indexOf Поиск { $indexOfArray: [ – массив. Array определенного expression>, , , указывает на поле, успешном ] } которое отсутствует, поиске $indexOfArray 41 возвращает возвращает значение индекс в null. массиве Если выражение выбора первого не входит в массив или вхождения. равно null, Если подстрока $indexOfArray не найдена, возвращает ошибку. возвращает -1 – целое число или число, которое может быть представлено целыми числами (например, 2.0), по умолчанию начало строки. – целое число $range Выводит { $range: [ , , – целое число, массив, ] } определяющее начало содержащий последовательности. последовательн – целое число, ость чисел в указывающее верхний соответствии с предел входными последовательности. параметрами и – операторами необязательный параметр. Целое число, указывающее значение приращения $reverse Возвращает { $reverseArray: } массив с возвращает пустой элементами в массив, когда аргумент обратном является пустым порядке массивом. Если аргумент содержит подмассивы, $reverseArray работает только на «верхнем» уровне и не изменяет содержание подмассивов Например, чтобы вывести первый и последний элемент массива AccountCD, нужно выполнить запрос: db.SERVICES.aggregate([ { $project:{ ServiceNM: 1, first: { $arrayElemAt: [ "$AccountCD", 0 ] },last: {$arrayElemAt:["$AccountCD", -1 ] }}}]) В результате выполнения запроса для каждой услуги будет выведен первый и последний элемент массива AccountCD: {"_id" : 2,"first" : "005488", "last" : "126112"} {"_id" : 1,"first" : "005488","last" : "126112"} { "_id" : 3,"first" : "005488","last" : "126112"} {"_id" : 4,"first" : "005488","last" : "126112"} Например, чтобы отобразить элементы массива AccountCD в обратном порядке, нужно выполнить запрос: db.SERVICES.aggregate([ {$project:{ServiceNM: 1, reverseAccount: { $reverseArray: "$AccountCD" }}}]) В результате выполнения запроса элементы массива AccountCD будут выведены в обратном порядке: {"_id" : 2,"ServiceNM" : "Электроснабжение", "reverseAccount" : [ "126112", " 443690", "443069", " 136160", " 136159", "136169", " 080047", " 080613", " 080270", " 015527", " 115705", "005488" ]} 43 Представлен фрагмент результата запроса только для одной услуги. Операторы управления документами и коллекциями Операторы управления документами и коллекциями (таблица 17) возвращают результат, который меняется в зависимости от значения, обрабатываемого оператором. Таблица 17 Операторы управления документами и коллекциями Выражение $collStats $geoNear Описание Возвращает Синтаксис { $collStats: Описание синтаксиса latencyStats добавляет статистику latencyStats: статистику задержек в относительно { histograms: возвращаемый коллекции }, документ Возвращает storageStats: {}}} { $geoNear: { geoNear dist.calculated – документы, options} } вычисляемое поле, основанные на содержащее близости к расстояние; геопространствен dist.location – поле ной точке, местоположения, включая поле содержащее местоположения местоположение, используемое при $first Получает первый db.Имя_коллекции. расчете Имя_поля – имя поля (FIRST) документ из aggregate([{$project:{ документов коллекции исходных Имя_поля : {$first : БД, среди значений документов, "$Имя_поля"}}}]) которых ищется $last содержащих первое, указанное в удовлетворяющее запросе поле Получает условию поиска Имя_поля – имя поля db.Имя_коллекции. 44 последний aggregate([{$project: коллекции БД, из документ из {Имя_поля : {$last : значений которых исходных "$Имя_поля"}}}]) выбирается последнее (LAST) документов, поле содержащих указанное в запросе поле Например, для вывода в разрезе услуг даты первой оплаты, нужно выполнить запрос: db.SERVICES.aggregate([{$unwind:"$PAYSUMMA"},{$group: {_id:"$ServiceNM",Date:{$first:"$PAYSUMMA.PayDate" }}} ]) В результате выполнения запроса для каждого значения поля ServiceNM коллекции SERVICES выведено первое записанное в базу значение поля PayDate документа подколлекции PAYSUMMA (рис. 111). Рис. 4.111. Результат выполнения запроса с оператором $first Например, чтобы вывести в разрезе услуг год первого начисления, нужно выполнить запрос: db.SERVICES.aggregate([{$unwind:"$NACHISLSUMMA"},{$group: {_id:"$ServiceNM",Date:{$last:"$NACHISLSUMMA.NachislYear" }}}]) В результате выполнения запроса для каждого значения поля ServiceNM коллекции SERVICES выведено последнее записанное в базу 45 значение поля NachislYear документа подколлекции NACHISLSUMMA (рис. 112). Рис. 4.112. Результат выполнения запроса с оператором $last Операторы выбора Операторы выбора (таблица 18) предназначены для статистического анализа данных в готовой выборке. Это довольно мощный и удобный инструмент, который присутствует во многих СУБД . Таблица 18 Операторы выбора Выражение Описание Синтаксис Описание синтаксиса 46 Оператор вычисляет выражение, и, { $cond: [ , , ] } либо три выражения в (expression) упорядоченном списке, либо три могут именованных параметра включать Возвращает результат первого { $ifNull: выражения или результат второго [ , выражения, если первое ] } $ifNull результат. Нулевой результат включает в себя примеры неопределенных значений или Выражения имена полей и системные переменные, объекты, массивы и операторы выражений недостающие поля. Результатом второго выражения может быть null Например, чтобы по услуге «Электроснабжение», вывести значения начисления равное 300, а по другим услугам вывести неизмененные значения начислений, нужно выполнить запрос: db.SERVICES.aggregate( [ { $project: { ServiceNM: 1, NACHISLSUMMA: { 47 $cond: { if: { $eq: [ "$ServiceNM", "Электроснабжение" ] }, then: 300, else: "$NACHISLSUMMA.NachislSum" } } } } ] ) В результате запроса для услуги «Элекстроснабжение» выведено значение 300, а для других услуг массив существующих значений начислений (рис. 4.113). Рис. 4.113. Фрагмент результата выполнения запроса с оператором $cond 48 Операторы преобразования типов Операторы преобразования типов предназначены для изменения типов данных на стороне СУРаБД (таблица 19). Таблица 19 Операторы преобразования типов Выражение Описание $convert Преобразует значение в указанный $toBool тип Преобразует значение в логическое $toDate $toDecimal значение Преобразует значение в дату Преобразует значение в дробное чис- $toDouble ло Преобразует значение в число двой- $toInt $toLong ной точности Преобразует значение в целое число Преобразует значение в число с пла- $toObjectId вающей запятой Преобразует значение в ObjectId $toString (идентификатор) Преобразует значение в строку Например, чтобы преобразовать при выводе результатов запроса тип поля номера лицевых счетов абонентов из строкового формата в числовой, нужно выполнить запрос: db.ABONENT.aggregate([{$project:{_id:1, Fio:1, _id:{ $convert: { input: "$_id", to: "int"}}}}]) или db.ABONENT.aggregate([{$project:{_id:1, Fio:1, _id:{ $toInt: "$_id"}}}]) В результате запроса выведены числовые значения идентификаторов: (для примера приведены первые три абонента) /* 1 */ { 49 "Fio" : {"fam" : "Аксенов","name" : "Сергей","otc" : "Анатольевич"}, "_id" : 5488 } /* 2 */ { "Fio" : {"fam" : "Мищенко","name" : "Евгений","otc" : "Владимирович" }, "_id" : 115705 } /* 3 */ { "Fio" : "Конюхов В.С.", "_id" : 15527 } Поскольку тип из строкового преобразован в числовой, то все нули в начале строки удалены. 50
«Агрегация в MongoDB. Агрегатные выражения метода aggregation» 👇
Готовые курсовые работы и рефераты
Купить от 250 ₽
Решение задач от ИИ за 2 минуты
Решить задачу
Помощь с рефератом от нейросети
Написать ИИ

Тебе могут подойти лекции

Смотреть все 70 лекций
Все самое важное и интересное в Telegram

Все сервисы Справочника в твоем телефоне! Просто напиши Боту, что ты ищешь и он быстро найдет нужную статью, лекцию или пособие для тебя!

Перейти в Telegram Bot