여러 개의 집계 결과를 한 번에 얻으려면 MongoDB의 $group 연산자와 $facet 단계를 함께 사용하면 됩니다. 이 글에서는 샘플 데이터를 준비한 뒤, 이름별 점수 합계와 카테고리별 점수 합계를 단 한 번의 쿼리로 동시에 계산하는 방법을 살펴보겠습니다.
샘플 데이터 생성
먼저 demo765 컬렉션을 만들고 세 개의 문서를 차례로 삽입합니다.
> db.demo765.insertOne({
... Name: "John",
... Category: "ComputerScience",
... SubjectName: "MongoDB",
... Marks: 75
... });
{ "acknowledged" : true, "insertedId" : ObjectId("5eb054525637cd592b2a4b01") }
> db.demo765.insertOne({
... Name: "John",
... Category: "ComputerScience",
... SubjectName: "MySQL",
... Marks: 85
... });
{ "acknowledged" : true, "insertedId" : ObjectId("5eb054525637cd592b2a4b02") }
> db.demo765.insertOne({
... Name: "Chris",
... Category: "10th",
... SubjectName: "Math",
... Marks: 98
... });
{ "acknowledged" : true, "insertedId" : ObjectId("5eb054535637cd592b2a4b03") }
저장된 문서 확인하기
find() 메서드를 사용하면 컬렉션의 모든 문서를 조회할 수 있습니다.
> db.demo765.find();
실행 결과는 다음과 같습니다.
{ "_id" : ObjectId("5eb054525637cd592b2a4b01"), "Name" : "John", "Category" : "ComputerScience", "SubjectName" : "MongoDB", "Marks" : 75 }
{ "_id" : ObjectId("5eb054525637cd592b2a4b02"), "Name" : "John", "Category" : "ComputerScience", "SubjectName" : "MySQL", "Marks" : 85 }
{ "_id" : ObjectId("5eb054535637cd592b2a4b03"), "Name" : "Chris", "Category" : "10th", "SubjectName" : "Math", "Marks" : 98 }
$group과 $facet으로 다중 집계 실행하기
아래 쿼리는 하나의 집계 파이프라인 안에서 두 가지 기준의 그룹화를 동시에 수행합니다. $facet은 여러 개의 하위 파이프라인을 각각 실행하고 그 결과를 하나의 문서로 묶어 반환하는 단계입니다.
> db.demo765.aggregate([
... { "$facet": {
... "ListOfName": [
... { "$group": {
... "_id": "$Name",
... "Marks": { "$sum": "$Marks" }
... }},
... { "$project": {
... "_id": false,
... "Name": "$_id",
... "Marks": 1
... }}
... ],
... "ListOfCategory": [
... { "$group": {
... "_id": "$Category",
... "Marks": { "$sum": "$Marks" }
... }},
... { "$project": {
... "_id": false,
... "Category": "$_id",
... "Marks": 1
... }}
... ]
... }}
... ]).pretty()
쿼리의 동작 방식을 단계별로 정리하면 다음과 같습니다.
- ListOfName —
Name필드를 기준으로$group하여 학생별Marks합계를 계산합니다. - ListOfCategory —
Category필드를 기준으로$group하여 카테고리별Marks합계를 계산합니다. - $project — 그룹 키로 생성된
_id를 제거하고 이를Name또는Category필드로 되돌려 결과를 읽기 좋게 다듬습니다.
실행 결과는 다음과 같습니다.
{
"ListOfName" : [
{
"Marks" : 98,
"Name" : "Chris"
},
{
"Marks" : 160,
"Name" : "John"
}
],
"ListOfCategory" : [
{
"Marks" : 98,
"Category" : "10th"
},
{
"Marks" : 160,
"Category" : "ComputerScience"
}
]
}
마무리
$facet과 $group을 조합하면 컬렉션을 한 번만 스캔하면서도 서로 다른 기준의 집계를 동시에 수행할 수 있습니다. 대시보드나 통계 리포트처럼 여러 지표를 한 번의 요청으로 가져와야 하는 상황에서 특히 유용한 패턴이니 꼭 기억해 두세요.