Document를 집계하는 방법

    1. DB의 모든 정보를 불러와 Application 단계에서 집계하는 방법
      • 네트워크 프로토콜을 통해MongoDB 외부로 정보를 넘겨야 하기 때문에 모든 Document로 인해 메모리 적재 + 네트워크 비용 발생
    2. MongoDB의 맵-리듀스 기능 이용
      • Java Script 엔진과 정보 교환을 위해 메모리 사용 (BSON to Javascript로 변환)
        • 사용자 쿼리에 대한 결과 필드를 가져와, 별도의 Thread에서 JavaScript를 실행(Aggregation도 비슷하지만, JS Thread가 아닌 C++로 실행되어 훨씬 빠름)
      • JSMode라는 설정을 사용하면 속도는 빨라지지만, 대량의 메모리가 필요
        • JSMode : false
          • Javascript 엔진에서 다시 MongoDB내부로 정보를 보내는 과정이 추가
        • JSMode : true
          • Javascript 엔진 내에서 Document를 grouping 하는 작업을 수행
      • Reduce 작업
        • 그룹핑된 Document 내에서 연산을 진행
          • JS Engine에서 수행
      • 자유도가 높아, MongoDB 내부에서 아직 유지중
      • 단, 다양한 집계 파이프라인의 명령어가 추가되면서 맵-리듀스 방식보다 더 많이 사용(Aggregation을 사용 못하는 경우 사용)

  1. MongoDB의 집계 파이프라인 기능을 이용
    • Document를 순차적으로 받아서 집계 처리를 MongoDB 내부에서 진행(적은 메모리로 빠른 속도 성능)
      • 순차적으로 받아서 처리하면 정확한 데이터가 맞을지..?
      • 전부 받아 오는 것은 동일한데,  메모리에 모두 올려서 처리할 것인지, 하나씩 받아서 처리하는 것의 차이?

 

Application

Map-Reduce

Pipeline

비고

자유도

좋다

좋다

나쁘다

 

처리 속도

가장 나쁘다.

보통

가장 좋다

pipeline 이 map-reduce 보다 10배 더 빠름

램 사용량

매우 높음

높음

낮음

 

처리 위치

App. 내부

자바스크립트 엔진

MongoDB 내부

 

참고 : https://stackoverflow.com/questions/32131828/mongo-map-reduce-or-aggregate-strategy

https://stackoverflow.com/questions/13908438/is-mongodb-aggregation-framework-faster-than-map-reduce

Aggreration 이란?

  • 여러 Document 들을 grouping하여 계산하여, 단일 결과를 반환
  • Aggregation, Map-reduce, 단일 목적 Aggregation이 존재
  • 처리 단계의 출력이 다음 단계의 입력으로 이어지는 형태로 연결된 구조 (linked list)
    • 누적으로 계산하는 형태

 

  • 주요 파이프라인
    • 출처 : "맛있는 MongoDB"
git clone https://github.com/Karoid/mongodb_tutorials.git
cd mongodb_tutorials/operating_expenses/

mongoimport -d operatin_expenses -c population --file population.json
mongoimport -d operatin_expenses -c city_or_province --file city_or_province.json
mongoimport -d operatin_expenses -c operating_expenses -c local --file local.json

 

Stage

설명

형식

$project

어떤 필드를 숨기고, 어떤 필드를 새로 만들지 정하는 역할

{$project:{필드 : bollean}}

{$project:{필드 : expression}}

$group

_id 값으로 지정된 내용이 같은 Document끼리 그룹화

{$group: {_id:expression, field1:{accumulator1:expression1},...}}

$match

Document를 필터링해서 반환. find문과 비슷한 역할

{$match:{쿼리}}

$unwind

입력 Document에서 배열 필드를 분해하여 각 요소에 대한 Document로 분리하여 출력

{$unwind:필드경로}

{

  $unwind :

   {

      path:필드경로,

      includeArrayIndex:문자,

      preserveNullAndEmptyArrays: bollean

   }

}

$out

파이프라인의 결과를 Collection에 기록

{ $out: "컬렉션명"}

 

$group

연산자

설명

예시

$first

그룹의 첫 번째 값을 반환.

$sort 를 해야 의미가 있음

{

  $group : { _id:"$그룹대상", 원하는필드명:{$first:"$값필드"} }

}

 

(max와 동일하다고 생각했지만 결과 값이 살짝 다름)

 

db.population.aggregate({$group:{_id:"$city_or_province",population:{$first:"$population"}}})

$last

그룹의 마지막 값을 반환.

$sort 를 해야 의미가 있음

{

  $group : { _id:"$그룹대상", 원하는필드명:{$last:"$값필드"} }

}

 

(min와 동일하다고 생각했지만 결과 값이 살짝 다름)

db.population.aggregate({$group:{_id:"$city_or_province",population:{$last:"$population"}}})

$max

그룹에서 해당 필드의 최대 값을 반환

{

  $group : { _id:"$그룹대상", 원하는필드명:{$max:"$값필드"} }

}

db.population.aggregate({$group:{_id:"$city_or_province",population:{$max:"$population"}}})

$min

그룹에서 해당 필드의 최소 값을 반환

{

  $group : { _id:"$그룹대상", 원하는필드명:{$min:"$값필드"} }

}

db.population.aggregate({$group:{_id:"$city_or_province",population:{$min:"$population"}}})

$avg

그룹에서 해당 필드의 평균 값을 반환

{

  $group : { _id:"$그룹대상", 원하는필드명:{$avg:"$값필드"} }

}

$sum

그룹에서 해당 필드의 합산 값을 반환

{

  $group : { _id:"$그룹대상", 원하는필드명:{$sum:"$값필드"} }

}

 

db.population.aggregate({$group:{_id:"$city_or_province",population:{$sum:"$population"}}})

$push

그룹에서 해당 필드의 모든 값을 배열에 넣어 반환.

중복을 제거하지 않음

{

  $group : { _id:"$그룹대상", 원하는필드명:{$push:"$값필드"} }

}

 

db.population.aggregate({$group:{_id:"$city_or_province",population:{$push:"$population"}}})

$addToSet

그룹에서 해당 필드의 모든 값을 배열에 넣어 반환.

반환하는 배열에 중복된 요소가 없음

{

  $group : { _id:"$그룹대상", 원하는필드명:{$addToSet:"$값필드"} }

}

 

db.population.aggregate({$group:{_id:"$city_or_province",population:{$addToSet:"$population"}}})

  • 샘플 데이터

$match

  • find 명령어와 비슷
#rating 이 4보다 크거나 같은 내역, id들을 배열의 형태로 정리하도록 명령($push)

> db.rating.aggregate([
{$match: {rating: {$gte:4}}}
, {$group: {_id: "$rating", user_ids:{$push:"$user_id"}}}
])

 

$unwind

  • 하나의 Document에 들어있는 배열 요소들을 각각의 Document에 하나의 값으로 갖도록 만드는 작업
반응형

+ Recent posts