Разберемся на примере
Вот так выглядит документ компании :
$unwind
Позволяет принимать документы в качестве входных данных , которые оказывают нормированное поле массива и производят выходные документы, такие , что есть один выходной документ для каждого элемента в массиве. источник
Итак, давайте вернемся к примерам наших компаний и посмотрим на использование этапов размотки. Этот запрос:
db.companies.aggregate([
{ $match: {"funding_rounds.investments.financial_org.permalink": "greylock" } },
{ $project: {
_id: 0,
name: 1,
amount: "$funding_rounds.raised_amount",
year: "$funding_rounds.funded_year"
} }
])
создает документы, содержащие массивы для суммы и года.
Потому что мы получаем доступ к собранной сумме и году финансирования для каждого элемента в массиве раундов финансирования. Чтобы исправить это, мы можем включить стадию раскрутки перед стадией проекта в этот конвейер агрегирования и параметризовать это, сказав, что мы хотим unwind
массив раундов финансирования:
db.companies.aggregate([
{ $match: {"funding_rounds.investments.financial_org.permalink": "greylock" } },
{ $unwind: "$funding_rounds" },
{ $project: {
_id: 0,
name: 1,
amount: "$funding_rounds.raised_amount",
year: "$funding_rounds.funded_year"
} }
])
Если мы посмотрим на funding_rounds
массив, мы знаем , что для каждого funding_rounds
, есть raised_amount
и funded_year
поле. Итак, unwind
будет для каждого из документов, которые являются элементами funding_rounds
массива, создать выходной документ. Теперь, в этом примере, наши значения - string
s. Но, независимо от типа значения для элементов в массиве, unwind
будет создан выходной документ для каждого из этих значений, так что в рассматриваемом поле будет только этот элемент. В случае funding_rounds
, этот элемент будет одним из этих документов в качестве значения funding_rounds
для каждого документа, который передается на нашу project
сцену. Результатом этого запуска является то, что теперь мы получаем amount
и year
. По одному на каждый раунд финансирования для каждой компаниив нашей коллекции. Это означает, что в результате нашего сопоставления было получено множество документов компании, и каждый из этих документов компании приводит к множеству документов. По одному на каждый раунд финансирования в каждом документе компании. unwind
выполняет эту операцию, используя документы, переданные ему со match
сцены. И все эти документы по каждой компании затем передаются на project
сцену.
Таким образом, все документы, в которых спонсором был Greylock (как в примере запроса), будут разделены на количество документов, равное количеству раундов финансирования для каждой компании, которая соответствует фильтру $match: {"funding_rounds.investments.financial_org.permalink": "greylock" }
. И каждый из этих результирующих документов затем будет передан нашему project
. Теперь unwind
создает точную копию для каждого документа, который он получает в качестве входных данных. Все поля имеют одинаковый ключ и значение, за одним исключением: это funding_rounds
поле, а не массив funding_rounds
документов, вместо этого имеет значение, которое представляет собой один документ, который представляет собой отдельный раунд финансирования. Итак, компания, у которой есть 4 раунда финансирования, приведет к unwind
созданию 4документы. Где каждое поле является точной копией, за исключением funding_rounds
поля, которое вместо того, чтобы быть массивом для каждой из этих копий, вместо этого будет отдельным элементом из funding_rounds
массива из документа компании, который unwind
в настоящее время обрабатывается. Таким образом, unwind
на следующий этап выводится больше документов, чем он получает на входе. Это означает, что наша project
сцена теперь получает funding_rounds
поле, которое, опять же, не является массивом, а представляет собой вложенный документ raised_amount
с funded_year
полями и. Таким образом, он project
будет получать несколько документов для каждой компании, match
включенной в фильтр, и поэтому может обрабатывать каждый из документов индивидуально и определять индивидуальную сумму и год для каждого раунда финансирования для каждой компании..
Согласно официальной документации mongodb:
$ unwind Деконструирует поле массива из входных документов для вывода документа для каждого элемента. Каждый выходной документ - это входной документ, в котором значение поля массива заменено элементом.
Объяснение на базовом примере:
В инвентарной описи есть следующие документы:
Следующие операции $ unwind эквивалентны и возвращают документ для каждого элемента в поле размеров . Если поле размеров не преобразуется в массив, но не отсутствует, имеет значение NULL или пустой массив, $ unwind рассматривает операнд, не являющийся массивом, как массив с одним элементом.
или
Над выводом запроса:
Зачем это нужно?
$ unwind очень полезен при выполнении агрегации. он разбивает сложный / вложенный документ на простой перед выполнением различных операций, таких как сортировка, поиск и т. д.
Чтобы узнать больше о $ unwind:
https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/
Чтобы узнать больше об агрегировании:
https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/
источник
рассмотрите приведенный ниже пример, чтобы понять эти данные в коллекции
Запрос - db.test1.aggregate ([{$ unwind: "$ sizes"}]);
вывод
источник
Позвольте мне объяснить, как это связано с РСУБД. Это заявление:
для обращения к документу / записи :
$ Проект / Select просто возвращает эти поля / столбцы как
Далее следует интересная часть Mongo: рассматривайте этот массив
tags : [ "fun" , "good" , "fun" ]
как другую связанную таблицу (не может быть таблицей поиска / справки, потому что значения имеют некоторое дублирование) с именем «теги». Помните, что SELECT обычно производит вещи вертикально, поэтому раскрутить «теги» означает разделить () вертикально на «теги» таблицы.Конечный результат $ project + $ unwind:
Переведите вывод в JSON:
Потому что мы не сказали Mongo опускать поле «_id», поэтому оно добавляется автоматически.
источник