Programing

MongoDB의 $ unwind 연산자는 무엇입니까?

crosscheck 2020. 10. 28. 07:45
반응형

MongoDB의 $ unwind 연산자는 무엇입니까?


이것은 MongoDB와의 첫날이므로 나와 함께 쉽게 가십시오 :)

$unwind연산자를 이해할 수 없습니다. 영어가 제 모국어가 아니기 때문일 수 있습니다.

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

프로젝트 운영자는 내가 이해할 수있는 것 SELECT입니다 (같지 않습니까?). 그러나 $unwind(citing) 은 모든 소스 문서 내에서 풀린 배열의 모든 구성원에 대해 하나의 문서를 반환합니다 .

이건 JOIN어때? 그렇다면, 방법의 결과 $project(와 _id, author, titletags필드)가 비교 될 수있다 tags배열?

참고 : MongoDB 웹 사이트에서 예제를 가져 왔지만 tags배열 의 구조를 모릅니다 . 태그 이름의 단순한 배열이라고 생각합니다.


먼저 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
}

결과 배열에서 변경되는 유일한 것은 tags 값에서 반환되는 것입니다. 작동 방식에 대한 추가 참조가 필요한 경우 여기 에 링크를 포함했습니다 . 이것이 도움이되기를 바라며 지금까지 제가 접한 최고의 NoSQL 시스템 중 하나에 대한 귀하의 진출에 행운을 빕니다.


$unwind 파이프 라인의 각 문서를 배열 요소 당 한 번씩 복제합니다.

귀하의 의견 파이프 라인이 두 요소를 하나의 문서 문서를 포함 그래서 만약 tags, {$unwind: '$tags'}을 제외하고는 동일한 두 개의 문서 문서로 파이프 라인을 변환 할 tags필드. 첫 번째 문서 tags에는 원래 문서 배열의 첫 번째 요소 tags가 포함되고 두 번째 문서 에는 두 번째 요소가 포함됩니다.


예를 들어 이해합시다

어떻게 '이다 회사의 문서는 다음과 같습니다

원본 문서

$unwind배열의 각 요소에 대한 하나 개의 출력 문서 거기되도록 출력 문서 배열 필드 값을 생성하고, 입력, 문서 등을 취할 수있게 해준다. 출처

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

unwind는 입력으로받는 것보다 더 많은 문서를 다음 단계로 출력하는 효과가 있습니다.

funding_rounds배열 을 보면 funding_rounds에 대해 raised_amountfunded_year필드 있음을 알 수 있습니다. 따라서 배열의 unwind요소 인 문서 각각에 대해 funding_rounds출력 문서가 생성됩니다. 이제이 예에서 값은 strings입니다. 그러나 배열의 요소 값 유형에 관계없이는 unwind이러한 값 각각에 대한 출력 문서를 생성하여 해당 필드가 해당 요소 만 갖도록합니다. 의 경우 funding_rounds해당 요소는 스테이지로 funding_rounds전달되는 모든 문서 의 값으로 이러한 문서 중 하나가 project됩니다. 이것을 실행 한 결과, 이제 우리는 amountyear. 에 대한 하나의 모든 회사에 대한 각각의 자금 조달 라운드우리 컬렉션에서. 이것이 의미하는 바는 우리의 매치가 많은 회사 문서를 생성하고 이러한 회사 문서 각각이 많은 문서를 생성한다는 것입니다. 모든 회사 문서의 각 펀딩 라운드마다 하나씩. 스테이지 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_amountfunded_year필드 가있는 중첩 문서라는 입니다. 따라서 필터를 사용하는 project각 회사에 대해 여러 문서를 받게 match되므로 각 문서를 개별적으로 처리하고 각 회사의 자금 조달 라운드마다 개별 금액과 연도를 식별 할 수 있습니다..


mongodb 공식 문서에 따라 :

$ unwind 입력 문서에서 배열 필드를 분해하여 각 요소에 대한 문서를 출력합니다. 각 출력 문서는 요소로 대체 ​​된 배열 필드의 값이있는 입력 문서입니다.

기본 예를 통한 설명 :

컬렉션 인벤토리에는 다음과 같은 문서가 있습니다.

{ "_id" : 1, "item" : "ABC", "sizes": [ "S", "M", "L"] }
{ "_id" : 2, "item" : "EFG", "sizes" : [ ] }
{ "_id" : 3, "item" : "IJK", "sizes": "M" }
{ "_id" : 4, "item" : "LMN" }
{ "_id" : 5, "item" : "XYZ", "sizes" : null }

다음 $ unwind 작업은 동일하며 sizes 필드의 각 요소에 대한 문서를 반환 합니다. 크기 필드가 배열로 해석되지 않지만 누락, 널 또는 빈 배열이 아닌 경우 $ unwind는 배열이 아닌 피연산자를 단일 요소 배열로 처리합니다.

db.inventory.aggregate( [ { $unwind: "$sizes" } ] )

또는

db.inventory.aggregate( [ { $unwind: { path: "$sizes" } } ] 

위 쿼리 출력 :

{ "_id" : 1, "item" : "ABC", "sizes" : "S" }
{ "_id" : 1, "item" : "ABC", "sizes" : "M" }
{ "_id" : 1, "item" : "ABC", "sizes" : "L" }
{ "_id" : 3, "item" : "IJK", "sizes" : "M" }

왜 필요한가요?

$unwind is very useful while performing aggregation. it breaks complex/nested document into simple document before performaing various operation like sorting, searcing etc.

To know more about $unwind :

https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/

To know more about aggregation :

https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/


Let me explain in a way corelated to RDBMS way. This is the statement:

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

to apply to the document / record:

{
 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 }
}

The $project / Select simply returns these field/columns as

SELECT author, title, tags FROM article

Next is the fun part of Mongo, consider this array tags : [ "fun" , "good" , "fun" ] as another related table (can't be a lookup/reference table because values has some duplication) named "tags". Remember SELECT generally produces things vertical, so unwind the "tags" is to split() vertically into table "tags".

The end result of $project + $unwind: 여기에 이미지 설명 입력

Translate the output to 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"}

Because we didn't tell Mongo to omit "_id" field, so it's auto-added.

The key is to make it table-like to perform aggregation.


consider the below example to understand this Data in a collection

{
        "_id" : 1,
        "shirt" : "Half Sleeve",
        "sizes" : [
                "medium",
                "XL",
                "free"
        ]
}

Query -- db.test1.aggregate( [ { $unwind : "$sizes" } ] );

output

{ "_id" : 1, "shirt" : "Half Sleeve", "sizes" : "medium" }
{ "_id" : 1, "shirt" : "Half Sleeve", "sizes" : "XL" }
{ "_id" : 1, "shirt" : "Half Sleeve", "sizes" : "free" }

참고URL : https://stackoverflow.com/questions/16448175/whats-the-unwind-operator-in-mongodb

반응형