MongoDB의 $unwind 연산자는 입력 도큐먼트에 포함된 배열 필드를 분해(deconstruct)하여, 배열의 각 요소마다 하나의 도큐먼트를 출력합니다. 이 연산자를 aggregate()와 함께 사용하면 원하는 항목의 개수(count)를 손쉽게 집계할 수 있습니다. 지금부터 실제 예제를 통해 단계별로 살펴보겠습니다.
1단계: 샘플 컬렉션 생성 및 데이터 삽입
먼저 예제에 사용할 demo478 컬렉션을 만들고 두 개의 도큐먼트를 삽입합니다. 각 도큐먼트는 Details.Information이라는 배열 필드를 가지며, 일부 요소의 Name 값은 null로 되어 있다는 점에 주목하세요.
> db.demo478.insertOne(
... {
... "Details" : {
... _id:1,
... "Information" : [
... {
... "Name" : "Chris",
... "Age":21
... },
... {
... "Name" : "David",
... "Age":23
... },
... {
... "Name" : null,
... "Age":22
... },
... {
... "Name" : null,
... "Age":24
... }
... ]
... }
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5e8204acb0f3fa88e2279092")
}
>
> db.demo478.insertOne(
... {
... "Details" : {
... _id:2,
... "Information" : [
... {
... "Name" : "Bob",
... "Age":21
... },
... {
... "Name" : null,
... "Age":20
... }
... ]
... }
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5e8204adb0f3fa88e2279093")
}
2단계: find() 메서드로 전체 도큐먼트 조회
find() 메서드를 사용하면 컬렉션에 저장된 모든 도큐먼트를 한눈에 확인할 수 있습니다.
> db.demo478.find();
위 명령을 실행하면 다음과 같은 결과가 출력됩니다.
{ "_id" : ObjectId("5e8204acb0f3fa88e2279092"), "Details" : { "_id" : 1, "Information" : [ { "Name" : "Chris", "Age" : 21 }, { "Name" : "David", "Age" : 23 }, { "Name" : null, "Age" : 22 }, { "Name" : null, "Age" : 24 } ] } }
{ "_id" : ObjectId("5e8204adb0f3fa88e2279093"), "Details" : { "_id" : 2, "Information" : [ { "Name" : "Bob", "Age" : 21 }, { "Name" : null, "Age" : 20 } ] } }3단계: $unwind와 aggregate()로 카운트 구하기
다음은 $unwind를 활용해 나이(Age)별로 이름(Name)이 null이 아닌 요소의 개수를 집계하는 쿼리입니다.
> db.demo478.aggregate([
... { "$unwind": "$Details.Information" },
... {
... "$group" : {
... "_id": "$Details.Information.Age",
... "count" : {
... "$sum": {
... "$cond": [
... { "$gt": [ "$Details.Information.Name", null ] },
... 1, 0
... ]
... }
... }
... }
... },
... { "$sort" : { "count" : -1 } }
... ])
애그리게이션 파이프라인 동작 설명
- $unwind:
$Details.Information배열을 분해하여 각 요소를 개별 도큐먼트로 만듭니다. - $group:
Age값을 기준으로 도큐먼트를 그룹화합니다. - $sum + $cond:
Name이 null보다 큰 값(즉, null이 아닌 경우)일 때만 1을 더해 유효한 이름의 개수를 계산합니다. - $sort: 최종 결과를
count기준 내림차순으로 정렬합니다.
위 쿼리를 실행하면 다음과 같은 결과가 출력됩니다.
{ "_id" : 21, "count" : 2 }
{ "_id" : 23, "count" : 1 }
{ "_id" : 24, "count" : 0 }
{ "_id" : 20, "count" : 0 }
{ "_id" : 22, "count" : 0 }결과를 해석해 보면, 나이가 21인 요소 중 이름이 존재하는 경우는 2건(Chris, Bob), 나이가 23인 경우는 1건(David)입니다. 반면 나이가 20, 22, 24인 요소들은 모두 Name이 null이므로 카운트가 0으로 집계된 것을 확인할 수 있습니다. 이처럼 $unwind와 조건부 집계를 조합하면 배열 내부 데이터를 유연하게 분석할 수 있습니다.