Давайте розберемося на прикладі
Ось як виглядає документ компанії :
Це $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
є a raised_amount
і funded_year
поле. Отже, unwind
буде для кожного з документів, що є елементами funding_rounds
масиву, виводиться вихідний документ. Тепер у цьому прикладі наші значення - string
s. Але, незалежно від типу значення для елементів масиву, unwind
буде видаватися вихідний документ для кожного з цих значень, таким чином, що у відповідному полі буде саме цей елемент. У випадку з funding_rounds
цим елементом буде один із цих документів як значення funding_rounds
для кожного документа, який передається на наш project
етап. Результатом, а потім запустити це, є те, що тепер ми отримаємо amount
і а year
. По одному на кожен раунд фінансування для кожної компаніїв нашій колекції. Це означає, що наш матч видав багато документів компанії, і кожен з цих документів компанії приводить до багатьох документів. По одному на кожен раунд фінансування в рамках кожного документа компанії. unwind
виконує цю операцію, використовуючи документи, передані їй зі match
сцени. І всі ці документи для кожної компанії потім передаються на project
сцену.
Таким чином, усі документи, де засновником був Грейлок (як у прикладі запиту), будуть розділені на ряд документів, рівних кількості раундів фінансування для кожної компанії, яка відповідає фільтру $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
з фільтром і, отже, можна обробити кожен документ окремо та визначити індивідуальну суму та рік для кожного раунду фінансування для кожної компанії.