문서 메뉴
문서 홈
/
MongoDB 매뉴얼
/ / /

$unwind (aggregation)

이 페이지의 내용

  • 정의
  • 호환성
  • 구문
  • 동작
  • 예제
  • 추가 리소스
$unwind

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

다음 환경에서 호스팅되는 배포에 $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>
}
}
필드
유형
설명
경로
문자열

배열 필드의 필드 경로입니다. 필드 경로를 지정하려면 필드 이름 앞에 달러 기호 $를 붙이고 따옴표로 묶습니다.

문자열

선택 사항. 요소의 배열 인덱스를 저장할 새 필드의 이름입니다. 이름은 달러 기호 $로 시작할 수 없습니다.

부울

선택 사항.

  • true 인 경우 path 이 null이거나 누락되었거나 빈 배열인 경우 $unwind 는 문서를 출력합니다.

  • false path 이 null이거나 누락되었거나 빈 배열인 경우 $unwind 는 문서를 출력하지 않습니다.

기본값은 false입니다.

  • 피연산자가 배열로 해석되지 않지만 누락되지 않았거나 null 또는 빈 배열인 경우 $unwind는 피연산자를 단일 요소 배열로 취급합니다.

  • 피연산자가 null이거나, 누락되었거나, 빈 배열 $unwind 인 경우 preserveNullAndEmptyArray 옵션에 설정된 동작을 따릅니다.

입력 문서에 존재하지 않는 필드의 경로를 지정하거나 필드가 빈 배열인 경우 $unwind 기본적으로 입력 문서를 무시하고 해당 입력 문서에 대한 문서를 출력하지 않습니다.

배열 필드가 누락되었거나, 널 또는 빈 배열이 있는 문서를 출력하려면 preserveNullAndEmptyArrays 옵션을 사용합니다.

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 은 채워진 배열입니다. $unwindsizes 필드의 각 요소에 대한 문서를 반환합니다.

  • 문서 "_id": 3에서 sizes는 단일 요소 배열로 해석됩니다.

  • sizes 필드를 단일 요소 배열로 축소할 수 없기 때문에 문서 "_id": 2, "_id": 4"_id": 5은 아무 것도 반환하지 않습니다.

참고

{ path: <FIELD> } 구문은 선택 사항입니다. 다음 $unwind 연산은 이에 해당합니다.

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

preserveNullAndEmptyArraysincludeArrayIndex 예제에서는 다음 컬렉션을 사용합니다.

db.inventory2.insertMany([
{ "_id" : 1, "item" : "ABC", price: NumberDecimal("80"), "sizes": [ "S", "M", "L"] },
{ "_id" : 2, "item" : "EFG", price: NumberDecimal("120"), "sizes" : [ ] },
{ "_id" : 3, "item" : "IJK", price: NumberDecimal("160"), "sizes": "M" },
{ "_id" : 4, "item" : "LMN" , price: NumberDecimal("10") },
{ "_id" : 5, "item" : "XYZ", price: NumberDecimal("5.75"), "sizes" : null }
])

다음 $unwind 작업은 preserveNullAndEmptyArrays 옵션을 사용하여 sizes 필드가 null이거나 누락되었거나 빈 배열인 문서를 포함합니다.

db.inventory2.aggregate( [
{ $unwind: { path: "$sizes", preserveNullAndEmptyArrays: true } }
] )

출력에는 sizes 필드가 null이거나 누락되었거나 빈 배열인 문서가 포함됩니다.

{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "S" }
{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "M" }
{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "L" }
{ "_id" : 2, "item" : "EFG", "price" : NumberDecimal("120") }
{ "_id" : 3, "item" : "IJK", "price" : NumberDecimal("160"), "sizes" : "M" }
{ "_id" : 4, "item" : "LMN", "price" : NumberDecimal("10") }
{ "_id" : 5, "item" : "XYZ", "price" : NumberDecimal("5.75"), "sizes" : null }

다음 $unwind 작업은 includeArrayIndex 옵션을 사용하여 출력에 배열 인덱스를 포함합니다.

db.inventory2.aggregate( [
{
$unwind:
{
path: "$sizes",
includeArrayIndex: "arrayIndex"
}
}])

이 작업은 sizes 배열을 해제하고 새 arrayIndex 필드에 배열 색인을 포함합니다. sizes 필드가 채워진 배열로 확인되지 않지만 누락되거나 null이거나 빈 배열인 경우 arrayIndex 필드는 null입니다.

{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "S", "arrayIndex" : NumberLong(0) }
{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "M", "arrayIndex" : NumberLong(1) }
{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "L", "arrayIndex" : NumberLong(2) }
{ "_id" : 3, "item" : "IJK", "price" : NumberDecimal("160"), "sizes" : "M", "arrayIndex" : null }

mongosh 에서 다음 문서를 사용하여 inventory2 라는 이름의 샘플 컬렉션을 만듭니다.

db.inventory2.insertMany([
{ "_id" : 1, "item" : "ABC", price: NumberDecimal("80"), "sizes": [ "S", "M", "L"] },
{ "_id" : 2, "item" : "EFG", price: NumberDecimal("120"), "sizes" : [ ] },
{ "_id" : 3, "item" : "IJK", price: NumberDecimal("160"), "sizes": "M" },
{ "_id" : 4, "item" : "LMN" , price: NumberDecimal("10") },
{ "_id" : 5, "item" : "XYZ", price: NumberDecimal("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" : NumberDecimal("80"), "sizes" : "S" }
{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "M" }
{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "L" }
{ "_id" : 2, "item" : "EFG", "price" : NumberDecimal("120") }
{ "_id" : 3, "item" : "IJK", "price" : NumberDecimal("160"), "sizes" : "M" }
{ "_id" : 4, "item" : "LMN", "price" : NumberDecimal("10") }
{ "_id" : 5, "item" : "XYZ", "price" : NumberDecimal("5.75"), "sizes" : null }
두 번째 단계:

$group 단계에서는 문서를 sizes 별로 그룹화하고 각 크기의 평균 가격을 계산합니다. 이 단계에서는 다음 문서를 다음 단계로 전달합니다.

{ "_id" : "S", "averagePrice" : NumberDecimal("80") }
{ "_id" : "L", "averagePrice" : NumberDecimal("80") }
{ "_id" : "M", "averagePrice" : NumberDecimal("120") }
{ "_id" : null, "averagePrice" : NumberDecimal("45.25") }
세 번째 단계:

$sort 단계에서는 문서를 내림차순으로 averagePrice 기준으로 정렬합니다. 이 연산은 다음과 같은 결과를 반환합니다.

{ "_id" : "M", "averagePrice" : NumberDecimal("120") }
{ "_id" : "L", "averagePrice" : NumberDecimal("80") }
{ "_id" : "S", "averagePrice" : NumberDecimal("80") }
{ "_id" : null, "averagePrice" : NumberDecimal("45.25") }

다음도 참조하세요.

mongosh 에서 다음 문서를 사용하여 sales 라는 이름의 샘플 컬렉션을 만듭니다.

db.sales.insertMany([
{
_id: "1",
"items" : [
{
"name" : "pens",
"tags" : [ "writing", "office", "school", "stationary" ],
"price" : NumberDecimal("12.00"),
"quantity" : NumberInt("5")
},
{
"name" : "envelopes",
"tags" : [ "stationary", "office" ],
"price" : NumberDecimal("19.95"),
"quantity" : NumberInt("8")
}
]
},
{
_id: "2",
"items" : [
{
"name" : "laptop",
"tags" : [ "office", "electronics" ],
"price" : NumberDecimal("800.00"),
"quantity" : NumberInt("1")
},
{
"name" : "notepad",
"tags" : [ "stationary", "school" ],
"price" : NumberDecimal("14.95"),
"quantity" : NumberInt("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" : NumberDecimal("12.00"), "quantity" : 5 } }
{ "_id" : "1", "items" : { "name" : "envelopes", "tags" : [ "stationary", "office" ], "price" : NumberDecimal("19.95"), "quantity" : 8 } }
{ "_id" : "2", "items" : { "name" : "laptop", "tags" : [ "office", "electronics" ], "price" : NumberDecimal("800.00"), "quantity" : 1 } }
{ "_id" : "2", "items" : { "name" : "notepad", "tags" : [ "stationary", "school" ], "price" : NumberDecimal("14.95"), "quantity" : 3 } }
두 번째 단계

두 번째 $unwind 단계에서는 items.tags 배열의 각 요소에 대해 새 문서를 출력합니다.

{ "_id" : "1", "items" : { "name" : "pens", "tags" : "writing", "price" : NumberDecimal("12.00"), "quantity" : 5 } }
{ "_id" : "1", "items" : { "name" : "pens", "tags" : "office", "price" : NumberDecimal("12.00"), "quantity" : 5 } }
{ "_id" : "1", "items" : { "name" : "pens", "tags" : "school", "price" : NumberDecimal("12.00"), "quantity" : 5 } }
{ "_id" : "1", "items" : { "name" : "pens", "tags" : "stationary", "price" : NumberDecimal("12.00"), "quantity" : 5 } }
{ "_id" : "1", "items" : { "name" : "envelopes", "tags" : "stationary", "price" : NumberDecimal("19.95"), "quantity" : 8 } }
{ "_id" : "1", "items" : { "name" : "envelopes", "tags" : "office", "price" : NumberDecimal("19.95"), "quantity" : 8 } }
{ "_id" : "2", "items" : { "name" : "laptop", "tags" : "office", "price" : NumberDecimal("800.00"), "quantity" : 1 } }
{ "_id" : "2", "items" : { "name" : "laptop", "tags" : "electronics", "price" : NumberDecimal("800.00"), "quantity" : 1 } }
{ "_id" : "2", "items" : { "name" : "notepad", "tags" : "stationary", "price" : NumberDecimal("14.95"), "quantity" : 3 } }
{ "_id" : "2", "items" : { "name" : "notepad", "tags" : "school", "price" : NumberDecimal("14.95"), "quantity" : 3 } }
세 번째 단계

$group 단계에서는 문서를 태그별로 그룹화하고 각 태그가 있는 품목의 총 판매 금액을 계산합니다.

{ "_id" : "writing", "totalSalesAmount" : NumberDecimal("60.00") }
{ "_id" : "stationary", "totalSalesAmount" : NumberDecimal("264.45") }
{ "_id" : "electronics", "totalSalesAmount" : NumberDecimal("800.00") }
{ "_id" : "school", "totalSalesAmount" : NumberDecimal("104.85") }
{ "_id" : "office", "totalSalesAmount" : NumberDecimal("1019.60") }

다음도 참조하세요.

← $unset (aggregation)