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