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