MongoDB에서 중첩된 필드 구조를 가진 문서를 다룰 때, 배열에 담긴 개수(Number) 값을 기준으로 데이터를 그룹화해야 하는 경우가 있습니다. 이 글에서는 $objectToArray, $unwind, $group 연산자를 조합하여 중첩 필드를 그룹화하는 방법을 단계별로 살펴보겠습니다.
1. 컬렉션 생성하기
먼저 중첩된 구조를 가진 문서들을 포함하는 컬렉션을 생성하겠습니다.
> db.demo99.insertOne(
... {
... 'Details':
... {
... 'X':
... {
... 'Values': [10,30,50],
... 'Number':3,
... },
... 'Y':
... {
... 'Values': [1000, 180],
... 'Number': 2,
... }
... }
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2d91eab8903cdd865577b9")
}
> db.demo99.insertOne(
... {
... 'Details':
... {
... 'X':
... {
... 'Values': [100,300,500,6000],
... 'Number':4,
... },
... 'Y':
... {
... 'Values': [10, 20,60],
... 'Number': 3,
... }
... }
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2d927bb8903cdd865577ba")
}
2. 저장된 문서 확인하기
find() 메서드를 사용하면 컬렉션의 모든 문서를 조회할 수 있습니다.
> db.demo99.find();
위 명령을 실행하면 다음과 같은 결과가 출력됩니다.
{ "_id" : ObjectId("5e2d91eab8903cdd865577b9"), "Details" : { "X" : { "Values" : [ 10, 30, 50 ], "Number" : 3 }, "Y" : { "Values" : [ 1000, 180 ], "Number" : 2 } } }
{ "_id" : ObjectId("5e2d927bb8903cdd865577ba"), "Details" : { "X" : { "Values" : [ 100, 300, 500, 6000 ], "Number" : 4 }, "Y" : { "Values" : [ 10, 20, 60 ], "Number" : 3 } } }
3. 집계 파이프라인으로 중첩 필드 그룹화하기
다음은 배열의 개수 값을 합산하여 중첩 필드를 그룹화하는 집계 쿼리입니다.
> db.demo99.aggregate([ { $project: { Count: { $objectToArray: "$Details" } } }, { $unwind: "$Count" }, { $group: { _id: "$Count.k", count: { $sum: "$Count.v.Number"} } } ])
쿼리를 실행하면 아래와 같은 결과를 얻을 수 있습니다.
{ "_id" : "Y", "count" : 5 }
{ "_id" : "X", "count" : 7 }
쿼리 동작 원리 살펴보기
이 집계 파이프라인은 세 단계로 구성되어 있습니다.
- $project + $objectToArray:
Details객체를 키(k)와 값(v) 쌍으로 이루어진 배열로 변환합니다. - $unwind: 변환된 배열의 각 요소를 개별 문서로 분리하여 처리 대상을 만듭니다.
- $group: 키(X, Y)를 기준으로 문서를 묶고,
$sum연산자로 각 그룹의Number값을 합산합니다.
결과적으로 X 필드의 Number 값(3 + 4 = 7)과 Y 필드의 Number 값(2 + 3 = 5)이 각각 그룹별로 집계되어 출력되는 것을 확인할 수 있습니다. 이처럼 $objectToArray를 활용하면 동적인 중첩 구조도 유연하게 그룹화할 수 있습니다.