집계
MongoDB 집계 프레임워크를 사용하여 보다 복잡한 쿼리 사용을 알아본다. (예. 월별매출, 제품별 매출, 사용자별 주문합계 등, cf. GROUP BY)
집계 프레임워크 개요
- 집계 파이프라인
- $project : 출력 도큐먼트상에 배치할 필드 지정
- $match : 처리될 도큐먼트를 선택하는 것. (= find())
- $limit : 다음 단계에 전달될 도큐먼트의 수 제한
- $skip : 지정된 수의 도큐먼트를 건너뛴다.
- $unwind : 배열을 확장하여 각 배열 항목에 대해 하나의 출력 도큐먼트 생성
- $group : 지정된 키로 도큐먼트를 그룹화
- $sort : 도큐먼트 정렬
- $geoNear : 지리 공간위치 근처의 도큐먼트 선택
- $out : 파이프라인의 결과를 컬렉션에 쓴다
- $redact : 특정 데이터에 대한 접근을 제어
db.products.aggregate([{$match: ...}, {$group: ...}, {$sort: ...} ] )
-> match, group, sort로 구성된 집계 프레임워크 파이프라인


전자상거래 집계 예제

- 상품, 카테고리, 리뷰
product = db.products.findOne({'slug':'wheelbarrow-9092'})
reviews_count = db.reviews.count({'product_id':product['_id']})
제품의 리뷰수 계산 예시 (5장내용)
db.reviews.aggregate([
{$group : { _id:'$product_id', // product_id로 입력 도큐먼트를 그룹화
count:{$sum:1} }} // 각 제품에 대한 리뷰수를 카운트
]);
// 각 제품에 대해 하나의 도큐먼트를 출력
{ "_id" : ObjectId("4c4b1...82"), "count" : 2 }
{ "_id" : ObjectId("4c4b1...81"), "count" : 3 }
//관심상품 한개에 대한 리뷰수 카운트
product = db.products.findOne({'slug': 'wheelbarrow-9092'})
ratingSummary = db.reviews.aggregate([
{$match : { product_id: product['_id']} }, // 하나의 상품 선택
{$group : { _id:'$product_id', // 결과의 첫 번째 도큐먼트를 반환
count:{$sum:1} }}
]).next();
{ "_id" : ObjectId("4c4b1...81"), "count" : 3 }
db.reviews.count({'product_id': product['_id']})
$match를 $group 앞에 두어야 처리해야하는 도큐먼트를 수를 줄이면서 연산할 수 있다.
- 평균 리뷰 계산하기
product = db.products.findOne({'slug': 'wheelbarrow-9092'})
ratingSummary = db.reviews.aggregate([
{$match : {'product_id': product['_id']}},
{$group : { _id:'$product_id',
average:{$avg:'$rating'}, // 제품의 평균 평점을 계산
count: {$sum:1}}}
]).next();
{
"_id" : ObjectId("4c4b1476238d3b4dd5003981"),
"average" : 4.333333333333333,
"count" : 3
}
- 등급별 리뷰 계산하기

countsByRating = db.reviews.aggregate([
{$match : {'product_id': product['_id']}}, // 제품선택
{$group : { _id:'$rating', // 등급별로 그룹화 ($rating)
count:{$sum:1}}} // 각 등급별 리뷰수 계산
]).toArray(); // 결과 커서를 배열로 변환
[ { "_id" : 5, "count" : 5 },
{ "_id" : 4, "count" : 2 },
{ "_id" : 3, "count" : 1 } ]
SELECT RATING, COUNT(*) AS COUNT
FROM REVIEWS
WHERE PRODUCT_ID = '4c4b1476238d3b4dd5003981'
GROUP BY RATING
SQL 쿼리
- 컬렉션 조인
db.products.aggregate([
{$group : { _id:'$main_cat_id',
count:{$sum:1}}}
]);
{ "_id" : ObjectId("6a5b1476238d3b4dd5000048"), "count" : 2 }
db.mainCategorySummary.remove({}); // mainCategorySummary 컬렉션에서 기존 도큐먼트를 제거
db.products.aggregate([
{$group : { _id:'$main_cat_id',
count:{$sum:1}}}
]).forEach(function(doc){
var category = db.categories.findOne({_id:doc._id}); //결과에 대한 카테고리 읽기
if (category !== null) { // 카테고리가 없을 때
doc.category_name = category.name;
}
else {
doc.category_name = 'not found';
}
db.mainCategorySummary.insert(doc); // 결합된 결과를 요약 컬렉션에 삽입
})