정의
호환성
다음 환경에서 호스팅되는 배포에 $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; } }
참고
파스칼 케이스용 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) });