MongoDB 집계 연산

집계 연산 개요

MongoDB 집계 연산은 다중 문서의 데이터를 처리해 계산 결과를 반환합니다. 문서 그룹을 대상으로 다양한 연산을 수행하며, 단일 목적 집계, 파이프라인 집계, MapReduce 세 가지 유형으로 구분됩니다.

  • 단일 목적 집계: 단일 컬렉션 대상의 기본 집계 함수 제공
  • 파이프라인 집계: 다단계 데이터 처리 모델 기반의 유연한 프레임워크
  • MapReduce: 대용량 데이터 분산 처리용 2단계 연산 모델

단일 목적 집계

db.collection.estimatedDocumentCount(), db.collection.count(), db.collection.distinct() 함수로 기본 집계 수행. 파이프라인에 비해 기능 제한적입니다.

연산기능
estimatedDocumentCount()컬렉션 전체 문서 수 추정
count()쿼리 매칭 문서 수 계산
distinct()필드 고유값 배열 반환
// 상품 컬렉션 문서 수
db.products.estimatedDocumentCount()

// 좋아요 50개 초과 문서 수
db.products.count({likes:{$gt:50}})

// 카테고리 고유값
db.products.distinct("category")

// 좋아요 90개 초과 상품의 카테고리
db.products.distinct("category",{likes:{$gt:90}})

샤딩 환경에선 db.collection.aggregate() 사용을 권장합니다.

집계 파이프라인

파이프라인 구조

다단계(stage) 처리 모델로 문서를 순차적 변환합니다.

pipeline = [$stage1, $stage2, ...$stageN];
db.collection.aggregate(pipeline, {options})

주요 파이프라인 단계

단계기능SQL 유사 연산
$match필터링WHERE
$project필드 선택/변환SELECT
$lookup조인LEFT JOIN
$group그룹화GROUP BY
$unwind배열 해체-

데이터 준비

const tags = ["db","nosql","cloud","dev","popular"];
const types = ["tech","social","travel","fiction","science"];
let products = [];

for(let i=0; i<50; i++){
  const typeIdx = Math.floor(Math.random()*types.length);
  const tagIdx = Math.floor(Math.random()*tags.length);
  const likes = Math.floor(Math.random()*100);
  const creator = "user" + Math.floor(Math.random()*10);
  
  products.push({
    name: "product-"+i,
    type: types[typeIdx],
    tags: [tags[tagIdx]],
    likes: likes,
    creator: { id: creator }
  })
}

db.products.insertMany(products);

$project 예제

// 필드 이름 변경
db.products.aggregate([{$project:{title:"$name"}}])

// 중첩 문서 필드 선택
db.products.aggregate([
  {$project:{name:1, "creator.id":1}}
])

$match + $project 결합

db.products.aggregate([
  {$match:{type:"tech"}},
  {$project:{_id:0, name:1, type:1}}
])

$group 연산

// 제작자별 좋아요 합계
db.products.aggregate([
  {$group:{_id:"$creator.id", totalLikes:{$sum:"$likes"}}}
])

// 제작자별 상품 유형 집합
db.products.aggregate([
  {$group:{_id:"$creator.id", types:{$addToSet:"$type"}}}
])

$unwind 활용

// 태그 배열 분해
db.products.aggregate([
  {$unwind:"$tags"},
  {$group:{_id:"$creator.id", uniqueTags:{$addToSet:"$tags"}}}
])

$lookup 조인 예제

// 주문-고객 조인
db.orders.aggregate([
  {$lookup:{
    from: "clients",
    localField: "clientId",
    foreignField: "id",
    as: "clientInfo"
  }}
])

집계 사례

카테고리별 상품 수

db.products.aggregate([
  {$group:{_id:"$type", count:{$sum:1}}},
  {$sort:{count:-1}}
])

태그 인기 순위

db.products.aggregate([
  {$match:{likes:{$gt:0}}},
  {$unwind:"$tags"},
  {$group:{_id:"$tags", popularity:{$sum:"$likes"}}},
  {$sort:{popularity:-1}}
])

MapReduce 연산

db.products.mapReduce(
  function(){emit(this.type, this.likes)},
  function(key,values){return Array.sum(values)},
  {query:{type:"travel"}, out:"results"}
)

MongoDB 5.0+부터는 집계 파이프라인 사용을 권장합니다.

태그: MongoDB Aggregation Pipeline MapReduce Group

6월 22일 20:53에 게시됨