개요
MongoDB에서 다단계(multilevel) $group 연산을 구현하려면 애그리게이션 파이프라인(aggregate)을 활용해야 합니다. 이 글에서는 실제 예제를 통해 여러 단계의 $group을 조합하여 데이터를 계층적으로 그룹화하고 요약하는 방법을 살펴보겠습니다.
1단계: 컬렉션 생성 및 문서 삽입
먼저 demo76 컬렉션에 샘플 문서들을 삽입해 보겠습니다.
> db.demo76.insertOne({ Name:"Chris","Age" : 21, "CountryName" : 'US' });
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2bd3e571bf0181ecc42281")
}
> db.demo76.insertOne({ Name:"Chris","Age" : 21, "CountryName" : 'US' });
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2bd3e571bf0181ecc42282")
}
> db.demo76.insertOne({ Name:"Chris","Age" : 23, "CountryName" : 'UK' });
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2bd3e571bf0181ecc42283")
}
> db.demo76.insertOne({ Name:"Chris","Age" : 23, "CountryName" : 'UK' });
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2bd3e571bf0181ecc42284")
}
> db.demo76.insertOne({ Name:"Chris","Age" : 21, "CountryName" : 'AUS' });
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2bd3e571bf0181ecc42285")
}
> db.demo76.insertOne({ Name:"Chris","Age" : 21, "CountryName" : 'AUS' });
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2bd3e571bf0181ecc42286")
}
> db.demo76.insertOne({ Name:"Chris","Age" : 23, "CountryName" : 'AUS' });
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2bd3e571bf0181ecc42287")
}
> db.demo76.insertOne({ Name:"Chris","Age" : 21, "CountryName" : 'UK' });
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2bd3e571bf0181ecc42288")
}2단계: 저장된 문서 확인
find() 메서드를 사용하면 컬렉션에 저장된 모든 문서를 조회할 수 있습니다.
> db.demo76.find();
위 명령은 다음과 같은 출력을 생성합니다.
{ "_id" : ObjectId("5e2bd3e571bf0181ecc42281"), "Name" : "Chris", "Age" : 21, "CountryName" : "US" }
{ "_id" : ObjectId("5e2bd3e571bf0181ecc42282"), "Name" : "Chris", "Age" : 21, "CountryName" : "US" }
{ "_id" : ObjectId("5e2bd3e571bf0181ecc42283"), "Name" : "Chris", "Age" : 23, "CountryName" : "UK" }
{ "_id" : ObjectId("5e2bd3e571bf0181ecc42284"), "Name" : "Chris", "Age" : 23, "CountryName" : "UK" }
{ "_id" : ObjectId("5e2bd3e571bf0181ecc42285"), "Name" : "Chris", "Age" : 21, "CountryName" : "AUS" }
{ "_id" : ObjectId("5e2bd3e571bf0181ecc42286"), "Name" : "Chris", "Age" : 21, "CountryName" : "AUS" }
{ "_id" : ObjectId("5e2bd3e571bf0181ecc42287"), "Name" : "Chris", "Age" : 23, "CountryName" : "AUS" }
{ "_id" : ObjectId("5e2bd3e571bf0181ecc42288"), "Name" : "Chris", "Age" : 21, "CountryName" : "UK" }3단계: 다단계 $group 쿼리 작성
다음은 다단계 $group을 구현하는 애그리게이션 쿼리입니다. 이 쿼리는 세 가지 주요 단계로 구성됩니다.
- $match: 이름(Name)이 "Chris"인 문서만 필터링합니다.
- 첫 번째 $group: 나이(Age)와 국가(CountryName)를 복합 키로 그룹화하고, 각 그룹의 문서 수를 $sum으로 계산합니다.
- 두 번째 $group: 나이별로 다시 그룹화한 뒤, $push를 통해 국가별 개수를 배열로 수집합니다.
마지막으로 $addFields와 $arrayToObject를 사용하여 배열 형태의 데이터를 읽기 쉬운 객체 형태로 변환합니다.
> db.demo76.aggregate([
... { "$match": { "Name": "Chris" }},
... { "$group": {
... "_id": { "Age": "$Age", "CountryName": "$CountryName" },
... "count": { "$sum": 1 }
... }},
... { "$group": {
... "_id": "$_id.Age",
... "CountryName": {
... "$push": {
... "k": "$_id.CountryName",
... "v": "$count"
... }
... }
... }},
... { "$addFields": {
... "CountryName": {
... "$arrayToObject": "$CountryName"
... }
... }}
... ]);실행 결과
위 쿼리는 다음과 같은 결과를 출력합니다.
{ "_id" : 23, "CountryName" : { "AUS" : 1, "UK" : 2 } }
{ "_id" : 21, "CountryName" : { "UK" : 1, "AUS" : 2, "US" : 2 } }결과 해석
출력 결과를 보면 나이가 23살인 그룹에는 AUS 출신이 1명, UK 출신이 2명 있고, 나이가 21살인 그룹에는 UK 출신이 1명, AUS 출신이 2명, US 출신이 2명 있는 것을 확인할 수 있습니다. 이처럼 다단계 $group을 활용하면 복잡한 조건의 데이터도 계층적으로 집계하여 한눈에 파악하기 쉬운 형태로 정리할 수 있습니다.