Computer >> 컴퓨터 >  >> 프로그래밍 >> MongoDB

MongoDB에서 중첩 문서 집계하는 방법 – $unwind와 $group 활용 가이드

MongoDB에서 중첩 문서 집계하는 방법

MongoDB에서 배열 형태로 중첩된 문서(nested documents)의 값을 집계하려면 애그리게이션 파이프라인의 $unwind$group 연산자를 조합하여 사용할 수 있습니다. $unwind는 배열 요소를 각각의 개별 문서로 분해해 주고, $group은 분해된 값들을 하나의 기준으로 묶어 최대값($max), 합계($sum), 평균($avg) 같은 통계를 계산합니다.

이 글에서는 실제 예제를 통해 중첩 배열 안의 Amount 값을 모두 펼친 뒤 전체 최대값을 구하는 과정을 단계별로 살펴보겠습니다.

1단계: 샘플 컬렉션 생성 및 문서 삽입

먼저 aggregateDemo라는 이름의 컬렉션을 만들고, ProductInformation 배열 안에 Product1 하위 배열이 중첩된 문서를 삽입합니다.

db.aggregateDemo.insertOne({
   "ProductInformation": [
      {
         "Product1": [
            { Amount: 50 },
            { Amount: 90 },
            { Amount: 30 }
         ]
      },
      {
         "Product1": [
            { Amount: 200 },
            { Amount: 30 },
            { Amount: 40 }
         ]
      },
      {
         "Product1": [
            { Amount: 150 },
            { Amount: 190 },
            { Amount: 198 }
         ]
      }
   ]
});

실행 결과 insertedId가 반환되며 문서가 정상적으로 저장됩니다. 같은 방식으로 두 번째 문서도 삽입합니다.

db.aggregateDemo.insertOne({
   "ProductInformation": [
      {
         "Product1": [
            { Amount: 100 },
            { Amount: 1002 },
            { Amount: 78 }
         ]
      },
      {
         "Product1": [
            { Amount: 75 },
            { Amount: 400 },
            { Amount: 600 }
         ]
      },
      {
         "Product1": [
            { Amount: 700 },
            { Amount: 500 },
            { Amount: 600 }
         ]
      }
   ]
});

2단계: find()로 저장된 문서 확인

find() 메서드와 pretty()를 함께 사용하면 컬렉션에 저장된 모든 문서를 보기 좋게 출력할 수 있습니다.

db.aggregateDemo.find().pretty();

위 명령을 실행하면 다음과 같이 중첩 구조를 가진 두 개의 문서가 출력됩니다.

{
   "_id" : ObjectId("5e04df58150ee0e76c06a04d"),
   "ProductInformation" : [
      {
         "Product1" : [
            { "Amount" : 50 },
            { "Amount" : 90 },
            { "Amount" : 30 }
         ]
      },
      {
         "Product1" : [
            { "Amount" : 200 },
            { "Amount" : 30 },
            { "Amount" : 40 }
         ]
      },
      {
         "Product1" : [
            { "Amount" : 150 },
            { "Amount" : 190 },
            { "Amount" : 198 }
         ]
      }
   ]
}
{
   "_id" : ObjectId("5e04df93150ee0e76c06a04e"),
   "ProductInformation" : [
      {
         "Product1" : [
            { "Amount" : 100 },
            { "Amount" : 1002 },
            { "Amount" : 78 }
         ]
      },
      {
         "Product1" : [
            { "Amount" : 75 },
            { "Amount" : 400 },
            { "Amount" : 600 }
         ]
      },
      {
         "Product1" : [
            { "Amount" : 700 },
            { "Amount" : 500 },
            { "Amount" : 600 }
         ]
      }
   ]
}

3단계: $unwind와 $group으로 중첩 문서 집계

이제 중첩된 Amount 값들을 집계하는 핵심 쿼리입니다. 파이프라인은 다음 순서로 동작합니다.

  • $unwind: "$ProductInformation" – ProductInformation 배열을 개별 문서로 분해합니다.
  • $unwind: "$ProductInformation.Product1" – 한 단계 더 깊은 Product1 배열 역시 개별 문서로 분해합니다.
  • $group – _id를 null로 지정해 전체 문서를 하나의 그룹으로 묶고, $max 연산자로 Amount 값 중 최대값을 계산합니다.
db.aggregateDemo.aggregate([
   { $unwind: "$ProductInformation" },
   { $unwind: "$ProductInformation.Product1" },
   {
      $group: {
         _id: null,
         MaximumAmount: { $max: "$ProductInformation.Product1.Amount" }
      }
   }
]);

쿼리 실행 결과는 다음과 같습니다.

{ "_id" : null, "MaximumAmount" : 1002 }

모든 중첩 배열의 Amount 값(50, 90, 30, 200, 30, 40, 150, 190, 198, 100, 1002, 78, 75, 400, 600, 700, 500, 600) 중 가장 큰 값인 1002가 MaximumAmount로 반환되었습니다. 이처럼 $unwind로 배열을 펼친 후 $group으로 묶으면, 여러 겹으로 중첩된 문서 안의 데이터도 손쉽게 집계할 수 있습니다. 필요에 따라 $max 대신 $sum이나 $avg를 사용하면 합계나 평균도 같은 방식으로 구할 수 있습니다.