정의
호환성
다음 환경에서 호스팅되는 배포에 $unwind 사용할 수 있습니다.
- MongoDB Atlas: 클라우드에서의 MongoDB 배포를 위한 완전 관리형 서비스 
- MongoDB Enterprise: MongoDB의 구독 기반 자체 관리 버전 
- MongoDB Community: MongoDB의 소스 사용 가능 무료 자체 관리 버전 
구문
필드 경로 피연산자 또는 문서 피연산자를 전달하여 배열 필드를 해제할 수 있습니다.
필드 경로 피연산자
배열 필드 경로를 $unwind로 전달할 수 있습니다. 이 구문을 사용할 때 $unwind는 필드 값이 null이거나 누락되었거나 빈 배열인 경우 문서를 출력하지 않습니다.
{ $unwind: <field path> } 
필드 경로를 지정할 때 필드 이름 앞에 달러 기호 $를 붙이고 따옴표로 묶습니다.
옵션이 있는 문서 피연산자
$unwind에 문서를 전달하여 다양한 동작 옵션을 지정할 수 있습니다.
{   $unwind:     {       path: <field path>,       includeArrayIndex: <string>,       preserveNullAndEmptyArrays: <boolean>     } } 
| 필드 | 유형 | 설명 | 
|---|---|---|
| 문자열 | 배열 필드의 필드 경로입니다. 필드 경로를 지정하려면 필드 이름 앞에 달러 기호  | |
| 문자열 | 선택 사항. 요소의 배열 인덱스를 저장할 새 필드의 이름입니다. 이름은 달러 기호  | |
| 부울 | 
동작
Non-Array Field Path(비배열 필드 경로)
- 피연산자가 배열로 해석되지 않지만 누락되지 않았거나 - null또는 빈 배열인 경우- $unwind는 피연산자를 단일 요소 배열로 취급합니다.
- 피연산자가 - null이거나, 누락되었거나, 빈 배열- $unwind인 경우 preserveNullAndEmptyArray 옵션에 설정된 동작을 따릅니다.
누락된 필드
입력 문서에 존재하지 않는 필드의 경로를 지정하거나 필드가 빈 배열인 경우 $unwind는 기본적으로 입력 문서를 무시하고 해당 입력 문서에 대한 문서를 출력하지 않습니다.
배열 필드가 누락되었거나, 널 또는 빈 배열이 있는 문서를 출력하려면 preserveNullAndEmptyArrays 옵션을 사용합니다.
예시
배열 Unwind
mongosh에서 다음 문서를 사용하여 inventory 라는 이름의 샘플 컬렉션을 만듭니다.
db.inventory.insertOne({ _id: 1, item: "ABC1", sizes: [ "S", "M", "L"] }) 
다음 집계는 $unwind 단계를 사용하여 sizes 배열의 각 요소에 대한 문서를 출력합니다.
db.inventory.aggregate( [ { $unwind : "$sizes" } ] ) 
이 연산은 다음과 같은 결과를 반환합니다.
{ _id: 1, item: "ABC1", sizes: "S" } { _id: 1, item: "ABC1", sizes: "M" } { _id: 1, item: "ABC1", sizes: "L" } 
각 문서는 이제 원래 sizes 배열의 값을 보유하는 sizes 필드의 값을 제외하고 입력 문서와 동일합니다.
누락되었거나 배열이 아닌 값
clothing 컬렉션을 살펴봅시다.
db.clothing.insertMany([   { _id: 1, item: "Shirt", sizes: [ "S", "M", "L"] },   { _id: 2, item: "Shorts", sizes: [ ] },   { _id: 3, item: "Hat", sizes: "M" },   { _id: 4, item: "Gloves" },   { _id: 5, item: "Scarf", sizes: null } ]) 
$unwind는 sizes 필드를 단일 요소 배열로 취급합니다.
- 필드가 존재합니다, 
- 값은 null이 아니며 
- 값은 빈 배열이 아닙니다. 
$unwind를 사용하여 sizes 배열을 확장합니다.
db.clothing.aggregate( [ { $unwind: { path: "$sizes" } } ] ) 
$unwind 작업은 다음을 반환합니다.
{ _id: 1, item: 'Shirt', sizes: 'S' }, { _id: 1, item: 'Shirt', sizes: 'M' }, { _id: 1, item: 'Shirt', sizes: 'L' }, { _id: 3, item: 'Hat', sizes: 'M' } 
- 문서 - "_id": 1에서- sizes는 채워진 배열입니다.- $unwind는- sizes필드에 있는 각 요소에 대한 문서를 반환합니다.
- 문서 - "_id": 3에서- sizes는 단일 요소 배열로 해석됩니다.
- sizes필드를 단일 요소 배열로 축소할 수 없기 때문에 문서- "_id": 2, "_id": 4및- "_id": 5은 아무 것도 반환하지 않습니다.
참고
{ path: <FIELD> } 구문은 선택 사항입니다. 다음 $unwind 작업은 동일합니다.
db.clothing.aggregate( [ { $unwind: "$sizes" } ] ) db.clothing.aggregate( [ { $unwind: { path: "$sizes" } } ] ) 
preserveNullAndEmptyArrays 개인정보 정책에 includeArrayIndex
preserveNullAndEmptyArrays 및 includeArrayIndex 예시에서는 다음 컬렉션을 사용합니다.
db.inventory2.insertMany([    { _id: 1, item: "ABC", price: Decimal128("80"), sizes: [ "S", "M", "L"] },    { _id: 2, item: "EFG", price: Decimal128("120"), sizes: [ ] },    { _id: 3, item: "IJK", price: Decimal128("160"), sizes: "M" },    { _id: 4, item: "LMN" , price: Decimal128("10") },    { _id: 5, item: "XYZ", price: Decimal128("5.75"), sizes: null } ]) 
preserveNullAndEmptyArrays
다음 $unwind 작업은 preserveNullAndEmptyArrays 옵션을 사용하여 sizes 필드가 null이거나, 누락되었거나, 빈 배열인 문서를 포함합니다.
db.inventory2.aggregate( [    { $unwind: { path: "$sizes", preserveNullAndEmptyArrays: true } } ] ) 
출력에는 sizes 필드가 null이거나 누락되었거나 빈 배열인 문서가 포함됩니다.
{ _id: 1, item: "ABC", price: Decimal128("80"), sizes: "S" } { _id: 1, item: "ABC", price: Decimal128("80"), sizes: "M" } { _id: 1, item: "ABC", price: Decimal128("80"), sizes: "L" } { _id: 2, item: "EFG", price: Decimal128("120") } { _id: 3, item: "IJK", price: Decimal128("160"), sizes: "M" } { _id: 4, item: "LMN", price: Decimal128("10") } { _id: 5, item: "XYZ", price: Decimal128("5.75"), sizes: null } 
includeArrayIndex
다음 $unwind 연산은 includeArrayIndex 옵션을 사용하여 출력에 배열 인덱스를 포함합니다.
db.inventory2.aggregate( [   {     $unwind:       {         path: "$sizes",         includeArrayIndex: "arrayIndex"       }    }]) 
이 작업은 sizes 배열을 해제하고 새 arrayIndex 필드에 배열 색인을 포함합니다. sizes 필드가 채워진 배열로 확인되지 않지만 누락되거나 null이거나 빈 배열인 경우 arrayIndex 필드는 null입니다.
{ _id: 1, item: "ABC", price: Decimal128("80"), sizes: "S", arrayIndex: Long(0) } { _id: 1, item: "ABC", price: Decimal128("80"), sizes: "M", arrayIndex: Long(1) } { _id: 1, item: "ABC", price: Decimal128("80"), sizes: "L", arrayIndex: Long(2) } { _id: 3, item: "IJK", price: Decimal128("160"), sizes: "M", arrayIndex: null } 
Unwound 값으로 그룹화
mongosh에서 다음 문서를 사용하여 inventory2라는 이름의 샘플 컬렉션을 만듭니다.
db.inventory2.insertMany([   { _id: 1, item: "ABC", price: Decimal128("80"), sizes: [ "S", "M", "L"] },   { _id: 2, item: "EFG", price: Decimal128("120"), sizes: [ ] },   { _id: 3, item: "IJK", price: Decimal128("160"), sizes: "M" },   { _id: 4, item: "LMN" , price: Decimal128("10") },   { _id: 5, item: "XYZ", price: Decimal128("5.75"), sizes: null } ]) 
다음 파이프라인은 sizes 배열을 해제하고 해제된 크기 값을 기준으로 결과 문서를 그룹화합니다.
db.inventory2.aggregate( [    // First Stage    {      $unwind: { path: "$sizes", preserveNullAndEmptyArrays: true }    },    // Second Stage    {      $group:        {          _id: "$sizes",          averagePrice: { $avg: "$price" }        }    },    // Third Stage    {      $sort: { "averagePrice": -1 }    } ] ) 
- 첫 번째 단계:
- $unwind단계는- sizes배열의 각 요소에 대해 새 문서를 출력합니다. 이 단계에서는 preserveNullAndEmptyArrays 옵션을 사용하여- sizes필드가 누락되었거나, null이거나, 빈 배열이 있는 문서를 출력에 포함합니다. 이 단계에서는 아래 문서를 다음 단계로 전달합니다.- { _id: 1, item: "ABC", price: Decimal128("80"), sizes: "S" } - { _id: 1, item: "ABC", price: Decimal128("80"), sizes: "M" } - { _id: 1, item: "ABC", price: Decimal128("80"), sizes: "L" } - { _id: 2, item: "EFG", price: Decimal128("120") } - { _id: 3, item: "IJK", price: Decimal128("160"), sizes: "M" } - { _id: 4, item: "LMN", price: Decimal128("10") } - { _id: 5, item: "XYZ", price: Decimal128("5.75"), sizes: null } 
- 두 번째 단계:
- $group단계에서는- sizes만큼 문서를 그룹화하고 각 크기의 평균 가격을 계산합니다. 이 단계에서는 다음 문서를 다음 단계로 전달합니다.- { _id: "S", averagePrice: Decimal128("80") } - { _id: "L", averagePrice: Decimal128("80") } - { _id: "M", averagePrice: Decimal128("120") } - { _id: null, averagePrice: Decimal128("45.25") } 
- 세 번째 단계:
- $sort단계에서는 문서를 내림차순으로- averagePrice씩 정렬합니다. 이 연산은 다음과 같은 결과를 반환합니다.- { _id : "M", averagePrice: Decimal128("120") } - { _id : "L", averagePrice: Decimal128("80") } - { _id : "S", averagePrice: Decimal128("80") } - { _id : null, averagePrice: Decimal128("45.25") } 
임베디드 배열 풀기
mongosh에서 다음 문서를 사용하여 sales라는 이름의 샘플 컬렉션을 만듭니다.
db.sales.insertMany( [   {    _id: "1",    items: [      {       name: "pens",       tags: [ "writing", "office", "school", "stationary" ],       price: Decimal128("12.00"),       quantity: Int32("5")      },      {       name: "envelopes",       tags: [ "stationary", "office" ],       price: Decimal128("19.95"),       quantity: Int32("8")      }     ]   },   {    _id: "2",    items: [      {       name: "laptop",       tags: [ "office", "electronics" ],       price: Decimal128("800.00"),       quantity: Int32("1")      },      {       name: "notepad",       tags: [ "stationary", "school" ],       price: Decimal128("14.95"),       quantity: Int32("3")      }     ]   } ]) 
다음 작업은 태그별로 판매된 품목을 그룹화하고 각 태그당 총 판매량을 계산합니다.
db.sales.aggregate([   // First Stage   { $unwind: "$items" },   // Second Stage   { $unwind: "$items.tags" },   // Third Stage   {     $group:       {         _id: "$items.tags",         totalSalesAmount:           {             $sum: { $multiply: [ "$items.price", "$items.quantity" ] }           }       }   } ]) 
- 첫 번째 단계
- 첫 번째 - $unwind단계는- items배열의 각 요소에 맞게 새 문서를 출력합니다.- { _id: "1", items: { name: "pens", tags: [ "writing", "office", "school", "stationary" ], price: Decimal128("12.00"), quantity: 5 } } - { _id: "1", items: { name: "envelopes", tags: [ "stationary", "office" ], price: Decimal128("19.95"), quantity: 8 } } - { _id: "2", items: { name: "laptop", tags: [ "office", "electronics" ], price: Decimal128("800.00"), quantity": 1 } } - { _id: "2", items: { name: "notepad", tags: [ "stationary", "school" ], price: Decimal128("14.95"), quantity: 3 } } 
- 두 번째 단계
- 두 번째 - $unwind단계에서는- items.tags배열의 각 요소에 대해 새 문서를 출력합니다.- { _id: "1", items: { name: "pens", tags: "writing", price: Decimal128("12.00"), quantity: 5 } } - { _id: "1", items: { name: "pens", tags: "office", price: Decimal128("12.00"), quantity: 5 } } - { _id: "1", items: { name: "pens", tags: "school", price: Decimal128("12.00"), quantity: 5 } } - { _id: "1", items: { name: "pens", tags: "stationary", price: Decimal128("12.00"), quantity: 5 } } - { _id: "1", items: { name: "envelopes", tags: "stationary", price: Decimal128("19.95"), quantity: 8 } } - { _id: "1", items: { name: "envelopes", tags: "office", "price" : Decimal128("19.95"), quantity: 8 } } - { _id: "2", items: { name: "laptop", tags: "office", price: Decimal128("800.00"), quantity: 1 } } - { _id: "2", items: { name: "laptop", tags: "electronics", price: Decimal128("800.00"), quantity: 1 } } - { _id: "2", items: { name: "notepad", tags: "stationary", price: Decimal128("14.95"), quantity: 3 } } - { _id: "2", items: { name: "notepad", "ags: "school", price: Decimal128("14.95"), quantity: 3 } } 
- 세 번째 단계
- $group단계에서는 문서를 태그별로 그룹화하고 각 태그가 있는 항목의 총 판매 금액을 계산합니다.- { _id: "writing", totalSalesAmount: Decimal128("60.00") } - { _id: "stationary", totalSalesAmount: Decimal128("264.45") } - { _id: "electronics", totalSalesAmount: Decimal128("800.00") } - { _id: "school", totalSalesAmount: Decimal128("104.85") } - { _id: "office", totalSalesAmount: Decimal128("1019.60") } 
이 페이지의 C# 예제에서는 Atlas 샘플 데이터 세트의 sample_mflix 데이터베이스 사용합니다. 무료 MongoDB Atlas cluster 생성하고 샘플 데이터 세트를 로드하는 방법을 학습하려면 MongoDB .NET/ C# 드라이버 문서에서 시작하기 를 참조하세요.
다음 Movie 클래스는 sample_mflix.movies 컬렉션의 문서를 모델링합니다.
public class Movie {     public ObjectId Id { get; set; }     public int Runtime { get; set; }          public string Title { get; set; }     public string Rated { get; set; }     public List<string> Genres { get; set; }     public string Plot { get; set; }          public ImdbData Imdb { get; set; }     public int Year { get; set; }     public int Index { get; set; }          public string[] Comments { get; set; }         []     public DateTime LastUpdated { get; set; } } 
참고
Pascal Case를 위한 ConventionPack
이 페이지의 C# 클래스는 속성 이름에 파스칼 표기법을 사용하지만, MongoDB 컬렉션의 필드 이름은 카멜 표기법을 사용합니다. 이 차이를 해결하기 위해 애플리케이션이 시작될 때 다음 코드를 사용하여 ConventionPack을 등록할 수 있습니다.
var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() }; ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true); 
MongoDB .NET/ C# 운전자 사용하여 $unwind 집계 파이프라인 에 단계를  추가하려면 PipelineDefinition 객체 에서 Unwind() 메서드를 호출합니다.
다음 예시 각 입력 Movie 문서 의 Genres 필드 반복하는 파이프라인 단계를 만듭니다. Genres 필드 의 각 값에 대해 스테이지에서는 새 Movie 문서 만들고 해당 Genres 필드 입력 문서 의 Genres 값으로 채웁니다.
var pipeline = new EmptyPipelineDefinition<Movie>()     .Unwind(m => m.Genres); 
AggregateUnwindOptions 객체 사용하여 Unwind() 메서드의 동작을 사용자 지정할 수 있습니다. 다음 예시 이전 예시 와 동일한 작업을 수행하지만 다음 옵션도 포함되어 있습니다.
- PreserveNullAndEmptyArrays- Genres필드 에 빈 배열 포함된 문서가 출력에 포함되도록 합니다.
- IncludeArrayIndex옵션은 각 출력 문서 에- Index라는 새 필드 추가합니다. 이 필드 의 값은 입력 문서의- Genres배열 에 있는- Genres필드 값의 배열 인덱스 입니다.
var pipeline = new EmptyPipelineDefinition<Movie>()     .Unwind(m => m.Genres,         new AggregateUnwindOptions<Movie>()         {            PreserveNullAndEmptyArrays = true,            IncludeArrayIndex = new ExpressionFieldDefinition<Movie, int>(                m => m.Index)          }); 
이 페이지의 Node.js 예제에서는 Atlas 샘플 데이터 세트의 sample_mflix 데이터베이스 사용합니다. 무료 MongoDB Atlas cluster 생성하고 샘플 데이터 세트를 로드하는 방법을 학습하려면 MongoDB Node.js 운전자 설명서에서 시작하기 를 참조하세요.
MongoDB Node.js 운전자 사용하여 집계 파이프라인 에 $unwind 단계를 추가하려면 파이프라인 객체 에서 $unwind 연산자 사용합니다.
다음 예시 각 입력 movie 문서 의 genres 필드 반복하는 파이프라인 단계를 만듭니다. genres 필드 의 각 값에 대해 스테이지에서는 새 movie 문서 만들고 해당 genres 필드 입력 문서 의 genres 값으로 채웁니다. 그런 다음 이 예시 에서는 집계 파이프라인 실행합니다.
const pipeline = [{ $unwind: "$genres" }]; const cursor = collection.aggregate(pipeline); return cursor; 
$unwind 메서드의 동작을 사용자 지정할 수 있습니다. 다음 예시 이전 예시 와 동일한 작업을 수행하지만 다음 옵션도 포함되어 있습니다.
- preserveNullAndEmptyArrays- genres필드 에 빈 배열 포함된 문서가 출력에 포함되도록 합니다.
- includeArrayIndex각 출력 문서 에- index이라는 새 필드 추가합니다. 이 필드 에는 입력 문서의- genres필드 에 있는- genres값의 배열 인덱스 포함되어 있습니다.
const pipeline = [   {     $unwind: {       path: "$genres",       preserveNullAndEmptyArrays: true,       includeArrayIndex: "index"     }   } ]; const cursor = collection.aggregate(pipeline); return cursor; 
자세히 알아보기
관련 메서드에 대해 자세히 학습 $group, $sum 및 $multiply 가이드를 참조하세요.
전체 예시에서 $unwind 를 사용하는 방법을 보려면 배열 및 그룹 데이터 풀기 튜토리얼을 참조하세요.