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

MongoDB에서 하위 문서(Subdocument)를 정렬하는 방법 – 집계 파이프라인 완벽 가이드

MongoDB에서 배열 형태로 저장된 하위 문서(subdocument)를 특정 기준에 따라 정렬해야 하는 경우가 종종 있습니다. 이번 글에서는 집계 파이프라인(Aggregation Pipeline)$unwind, $project, $sort, $group 연산자를 활용하여 중첩된 하위 문서를 정렬하는 방법을 단계별로 살펴보겠습니다.

1. 샘플 컬렉션 생성하기

먼저 문서를 포함하는 컬렉션을 생성합니다. 아래 예제에서는 직원 정보를 중첩 배열 구조로 담고 있는 문서를 하나 삽입합니다.

> db.demo136.insertOne(
...    {
...       "Name":"Chris",
...       "Details":[
...          {
...             "Id":"101",
...             "EmployeeName":"Mike",
...             "EmployeeDetails":[
...                {
...                   "EmpId":1001,
...                   "Salary":1000
...                },
...                {
...                   "EmpId":1002,
...                   "Salary":2000
...                }
...             ]
...          },
...          {
...             "Id":"102",
...             "EmployeeName":"David",
...             "EmployeeDetails":[
...                   {
...                      "EmpId":1004,
...                      "Salary":4000
...                   },
...                   {
...                      "EmpId":1005,
...                      "Salary":5000
...                   }
...             ]
...          }
...       ]
...    }
... );
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e31b15cfdf09dd6d085399f")
}

2. 저장된 문서 확인하기

find() 메서드를 사용하면 컬렉션에 저장된 모든 문서를 조회할 수 있습니다.

> db.demo136.find();

위 명령을 실행하면 다음과 같은 결과가 출력됩니다.

{
   "_id" : ObjectId("5e31b15cfdf09dd6d085399f"), "Name" : "Chris", "Details" : [
      { "Id" : "101", "EmployeeName" : "Mike", "EmployeeDetails" : [ { "EmpId" : 1001, "Salary" : 1000 },
      { "EmpId" : 1002, "Salary" : 2000 } ] },
      { "Id" : "102", "EmployeeName" : "David", "EmployeeDetails" : [ { "EmpId" : 1004, "Salary" : 4000 },
      { "EmpId" : 1005, "Salary" : 5000 } ] }
   ] 
}

3. 하위 문서 정렬 쿼리 작성하기

이제 핵심인 하위 문서 정렬 쿼리입니다. 각 직원(Details)별로 급여 합계를 계산한 뒤, 그 합계를 기준으로 내림차순 정렬하고 다시 원래 문서 구조로 그룹화합니다.

> db.demo136.aggregate([
...    { $unwind: "$Details" },
...    {
...       $project: {
...          Name: 1,
...          Details: 1,
...          SalaryTotal: {
...             $sum: "$Details.EmployeeDetails.Salary"
...          }
...       }
...    },
...    { $sort: { SalaryTotal: -1 } },
...    {
...       $group: {
...          _id: "$_id",
...          Name: { $first: "$Name" },
...          Details: { $push: "$Details" }
...       }
...    }
... ]).pretty()

쿼리 동작 원리

  • $unwind: Details 배열의 각 요소를 개별 문서로 분해하여 처리할 수 있게 만듭니다.
  • $project + $sum: 각 하위 문서에 포함된 직원들의 급여(Salary) 합계를 SalaryTotal 필드로 계산합니다.
  • $sort: 계산된 SalaryTotal 값을 기준으로 내림차순(-1) 정렬을 수행합니다.
  • $group: 정렬된 순서를 유지한 채 _id를 기준으로 문서를 다시 하나로 묶어 원본 구조를 복원합니다.

4. 실행 결과 확인

위 집계 쿼리를 실행하면 급여 합계가 높은 순서대로 하위 문서가 재배열된 것을 확인할 수 있습니다.

{
   "_id" : ObjectId("5e31b15cfdf09dd6d085399f"),
   "Name" : "Chris",
   "Details" : [
      {
         "Id" : "102",
         "EmployeeName" : "David",
         "EmployeeDetails" : [
            {
               "EmpId" : 1004,
               "Salary" : 4000
            },
            {
               "EmpId" : 1005,
               "Salary" : 5000
            }
         ]
      },
      {
         "Id" : "101",
         "EmployeeName" : "Mike",
         "EmployeeDetails" : [
            {
               "EmpId" : 1001,
               "Salary" : 1000
            },
            {
               "EmpId" : 1002,
               "Salary" : 2000
            }
         ]
      }
   ]
}

결과를 보면 원래는 Mike(Id: 101)가 먼저였지만, 급여 합계가 더 높은 David(Id: 102)가 첫 번째로 정렬된 것을 알 수 있습니다. 이처럼 MongoDB의 집계 파이프라인을 활용하면 중첩 배열 안의 하위 문서도 손쉽게 원하는 기준으로 정렬할 수 있습니다.