MongoDB 집계 프레임워크로 전체 평균 이하 점수 학생 찾기
조건에 맞는 데이터를 추출하려면 MongoDB의 aggregate() 메서드를 활용하면 됩니다. 이 예제에서는 각 시험 점수를 "Value1", "Value2", "Value3" 필드로 저장했다고 가정합니다.
먼저 샘플 문서가 담긴 컬렉션을 생성해 보겠습니다.
> db.demo432.insertOne(
... {
... "_id" : 101,
... "Name" : "David",
... "Value1" : 67,
... "Value2" : 87,
... "Value3" : 78
... }
... )
{ "acknowledged" : true, "insertedId" : 101 }
> db.demo432.insertOne(
... {
... "_id" : 102,
... "Name" : "Sam",
... "Value1" : 98,
... "Value2" : 45,
... "Value3" : 90
... }
... )
{ "acknowledged" : true, "insertedId" : 102 }
find() 메서드를 사용해 컬렉션의 모든 문서를 확인합니다.
> db.demo432.find();
실행 결과는 다음과 같습니다.
{ "_id" : 101, "Name" : "David", "Value1" : 67, "Value2" : 87, "Value3" : 78 }
{ "_id" : 102, "Name" : "Sam", "Value1" : 98, "Value2" : 45, "Value3" : 90 }집계 파이프라인 쿼리 작성하기
다음은 첫 번째 시험(Value1) 점수가 세 과목 시험의 전체 평균보다 낮은 학생의 이름을 가져오는 쿼리입니다.
> db.demo432.aggregate([{
... $project: {
... Name: '$Name',
... Value1: '$Value1',
... average: {
... $avg: ['$Value1', '$Value2', '$Value3']
... }
... }
... },
... {
... $group: {
... _id: null,
... NameValue1: {
... $push: {
... "Name": "$Name",
... "Value1": "$Value1"
... }
... },
... totalAverage: {
... $avg: '$average'
... }
... }
... },
... { $project:
... { lessthanAverageNames:
... {
... $map:
... {
... input: {
... $filter: {
... input: "$NameValue1",
... as: "out",
... cond: {
... $lt: ["$$out.Value1", "$totalAverage"]
... }
... }
... },
... as: "o",
... in: "$$o.Name"
... }
... }
... }
... }
... ]);쿼리 실행 결과:
{ "_id" : null, "lessthanAverageNames" : [ "David" ] }쿼리 동작 원리
이 집계 파이프라인은 크게 세 단계로 구성됩니다.
- $project 단계 — 각 문서마다 학생 이름(Name), 첫 번째 시험 점수(Value1)와 함께 세 시험 점수의 개인별 평균(average)을 계산합니다.
- $group 단계 — 모든 문서를 하나의 그룹으로 묶어 학생 이름과 Value1 점수 목록(NameValue1)을 배열로 만들고, 개인별 평균 값들을 종합한 전체 평균(totalAverage)을 산출합니다.
- $map + $filter 단계 — Value1 점수가 totalAverage보다 작은($lt) 학생만 걸러낸 뒤, 해당 학생의 이름만 추출하여 최종 배열(lessthanAverageNames)을 완성합니다.
결과를 살펴보면 David의 첫 번째 시험 점수(67점)는 전체 평균(약 77.5점)보다 낮아 결과에 포함되었고, Sam(98점)은 평균을 넘기 때문에 제외되었습니다. 이처럼 MongoDB의 집계 프레임워크를 활용하면 복잡한 통계 조건도 몇 단계의 파이프라인만으로 손쉽게 처리할 수 있습니다.