Что такое оператор $ unwind в MongoDB?

это мой первый день с MongoDB поэтому, пожалуйста, полегче со мной :)

я не могу понять $unwind оператор, возможно, потому, что английский не является моим родным языком.

db.article.aggregate(
    { $project : {
        author : 1 ,
        title : 1 ,
        tags : 1
    }},
    { $unwind : "$tags" }
);

оператор проекта-это то, что я могу понять, я полагаю (это похоже на SELECT, не так ли?). Но потом ... --1--> (цитата) возвращает один документ для каждого члена размотанного массива в каждом исходном документе.

это как JOIN? Если да, как результат $project_id, author, title и tags поля) можно сравнить с tags массив?

Примечание: я взял пример с сайта MongoDB, я не знаю структуру tags массив. Я думаю, это просто набор имен тегов.

4 ответов


во-первых, добро пожаловать в MongoDB!

дело в том, что MongoDB использует подход "NoSQL" к хранению данных, поэтому погибают мысли о выборе, присоединении и т. д. из твоего разума. Он хранит ваши данные в виде документов и коллекций, что позволяет динамично добавлять и получать данные из ваших хранилищ.

это, как говорится, для того, чтобы понять концепцию за параметром $unwind, вы сначала должны поймите, что говорит прецедент, который вы пытаетесь процитировать. Пример документа изmongodb.org следующим образом:

{
 title : "this is my title" ,
 author : "bob" ,
 posted : new Date () ,
 pageViews : 5 ,
 tags : [ "fun" , "good" , "fun" ] ,
 comments : [
             { author :"joe" , text : "this is cool" } ,
             { author :"sam" , text : "this is bad" }
 ],
 other : { foo : 5 }
}

обратите внимание, как теги на самом деле массив из 3 элементов, в этом случае "весело", "хорошо" и "весело".

то, что делает $unwind, позволяет вам отслаивать документ для каждого элемента и возвращает этот результирующий документ. Чтобы подумать об этом в классическом подходе, это было бы равносильно "для каждого элемента в массиве тегов, верните документ только с этим пунктом".

таким образом, результат выполнения следующий:

db.article.aggregate(
    { $project : {
        author : 1 ,
        title : 1 ,
        tags : 1
    }},
    { $unwind : "$tags" }
);

вернет следующие документы:

{
     "result" : [
             {
                     "_id" : ObjectId("4e6e4ef557b77501a49233f6"),
                     "title" : "this is my title",
                     "author" : "bob",
                     "tags" : "fun"
             },
             {
                     "_id" : ObjectId("4e6e4ef557b77501a49233f6"),
                     "title" : "this is my title",
                     "author" : "bob",
                     "tags" : "good"
             },
             {
                     "_id" : ObjectId("4e6e4ef557b77501a49233f6"),
                     "title" : "this is my title",
                     "author" : "bob",
                     "tags" : "fun"
             }
     ],
     "OK" : 1
}

обратите внимание, что единственное изменение в результирующем массиве-это то, что возвращается в значении тегов. Если вам нужна дополнительная ссылка на то, как это работает, я включил ссылку здесь. Надеюсь, это поможет, и удачи с вашим набегом в одну из лучших систем NoSQL, с которыми я столкнулся таким образом далеко.


$unwind дублирует каждый документ в конвейере, один раз на элемент массива.

Итак, если ваш входной конвейер содержит один документ статьи с двумя элементами в tags, {$unwind: '$tags'} преобразует конвейер в два документа статьи, которые одинаковы, за исключением


давайте разберемся на примере

вот как компанию документ выглядит так:

original document

на $unwind позволяет нам принимать документы в качестве входных данных, которые имеют поле со значением массива и производят выходные документы, так что есть один выходной документ для каждого элемента в массиве. источник

The $unwind stage

Итак, давайте вернитесь к примерам наших компаний и посмотрите на использование этапов размотки. Этот запрос:


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"
    } }
])

производит документы, массивы для суммы и год.

project output

потому что мы получаем доступ к собранной сумме и финансируемому году для каждого элемента в массиве раундов финансирования. Чтобы исправить это, мы можем включить этап размотки перед этапом нашего проекта в этот конвейер агрегации и параметризовать это, сказав, что мы хотим 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"
    } }
])

unwind has the effect of outputting to the next stage more documents than it receives as input

если мы посмотрим на funding_rounds массив, мы знаем, что для каждого funding_rounds, есть raised_amount и a


позвольте мне объяснить в пути corelated к РСУБД способом. Это утверждение:

db.article.aggregate(
    { $project : {
        author : 1 ,
        title : 1 ,
        tags : 1
    }},
    { $unwind : "$tags" }
);

применить к документ / запись:

{
 title : "this is my title" ,
 author : "bob" ,
 posted : new Date () ,
 pageViews : 5 ,
 tags : [ "fun" , "good" , "fun" ] ,
 comments : [
             { author :"joe" , text : "this is cool" } ,
             { author :"sam" , text : "this is bad" }
 ],
 other : { foo : 5 }
}

на $project / Select просто возвращает эти поля/столбцы как

выберите автор, название, теги С статьи

далее это забавная часть Монго, рассмотрим этот массив tags : [ "fun" , "good" , "fun" ] как другая связанная таблица (не может быть таблица поиска / ссылки, потому что значения имеют некоторое дублирование) с именем "теги". Помните, что SELECT обычно производит вертикальные вещи, поэтому размотайте "теги" на split () вертикально в таблице "теги".

конечный результат $project + $unwind: enter image description here

перевести вывод в JSON:

{ "author": "bob", "title": "this is my title", "tags": "fun"},
{ "author": "bob", "title": "this is my title", "tags": "good"},
{ "author": "bob", "title": "this is my title", "tags": "fun"}

потому что мы не сказали Монго опустить поле "_id", поэтому оно автоматически добавлено.

ключ сделать его стол-как к выполнить агрегацию.