본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


몽고DB/Java 몽고DB

MongoTemplate Aggregate

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2019. 6. 21.

 

 

Mongotemplate를 활용해서 집계함수를 실행하는 방법이다.

아래와 같은 데이터가 있다고 하자.

{
  "_id":ObjectId("507f1f77bcf86cd799439011"),  //고유 아이디
  "date" : ISODate("2019-06-21 10:03:46.000Z"),  //날짜 데이터
  "text":"test",  //단순 텍스트
  "number":1234,  //숫자
  "type1":"A",  //그룹핑할 데이터1
  "type2":"AA"  //그룹핑할 데이터2
}, 
{
  "_id":ObjectId("54af1e77gcfq6qdr22u39914"),
  "date" : ISODate("2019-06-21 10:03:46.000Z"),
  "text":"text text..",
  "number":1234,
  "type1":"B",
  "type2":"BB"
}
.....

Mongotemplate를 활용해서 집계함수를 실행하려면 여러개의 조건과 경우, 행위를 지정해서 할 수 있다.

먼저 대표적으로 프로젝트에 대한 행동 즉, 집계를 해올 대상을 선정하는 클래스이다.

ProjectionOperation dateProjection = null;  //집계를 해올 대상 선정

프로젝트오퍼레이션이라는 클래스를 굳이 추가하지 않아도 집계함수가 동작을 하는데, 해당클래스를 사용하면 데이터 파싱같은게 좀더 쉽다. 아래코드를 보자.

ProjectionOperation dateProjection = Aggregation.project()
		.and("date").dateAsFormattedString("%Y-%m-%d").as("conv_date")
		.and("date").as("reg_origin_date")
		.and("number").as("number")
		.and("type1").as("type1")
		.and("type2").as("type2")
		.and("_id").as("_id");		

해당에 선언된 데이터만 조회대상에 선정이 된다. 여기서보면 text항목이 빠져 있는데 text는 집계함수에서 사용되지도 않으며 출력되지 않는다.

흥미로운것은 첫번째줄 라인이다. 해당 형식처럼 써주면 날짜형식이 우리가 잘 알고 있는 YYYY-MM-DD형식으로 나오게 된다.

 

다음으로 조건절이다.

MatchOperation where = null;  //조건절
LocalDate  start_day = LocalDate .parse("2019-06-19");
LocalDate  end_day = LocalDate .parse("2019-06-21");
where = Aggregation.match( 
        new Criteria().andOperator(
			Criteria.where("reg_origin_date")
            .gte(start_day.atTime(0,0,0))
            .lte(end_day.atTime(0,0,0))
		)
);

해당 조건절에서는 날짜를 조건으로 주어 보았다. 해당 날짜형식은 맨 위에서 별칭으로한 reg_origin_date에 조건절로 들어 갔다.

이후정렬이다.

SortOperation sort = null; //정렬
sort = Aggregation.sort(Sort.Direction.DESC, "conv_date");

conv_date라는 별칭을 준 속성으로 정렬을 하게 하였다.

마지막으로 group을 하는 부분이다.

GroupOperation groupBy = null;  //그룹핑
groupBy= Aggregation.group("conv_date","type1","type2").count().as("count")
          .sum("number").as("num_sum");

group메소드에는 그룹핑을 할 대상을 선정한다. 그리고 count메소드로 카운트를 호출하면 갯수가 집계된다.

sum이라는 녀석은 합계를 구하도록 되어있다. 물론 숫자에 한에서만 동작한다.

이를 1개의 코드로 나타내 보았다.

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;

import java.util.HashMap;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import org.springframework.data.mongodb.core.aggregation.MatchOperation;
import org.springframework.data.mongodb.core.aggregation.ProjectionOperation;
import org.springframework.data.mongodb.core.aggregation.SortOperation;
import org.springframework.data.mongodb.core.query.Criteria;

import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;

@Controller
public class TestController {


    @AutoWired
    private MongoTemplate template;


    @RequestMapping(value = "/test")
    @ResponseBody
    public void tester(){

		ProjectionOperation dateProjection = Aggregation.project() //대상선정
				.and("date").dateAsFormattedString("%Y-%m-%d").as("conv_date")
				.and("date").as("reg_origin_date")
				.and("number").as("number")
				.and("type1").as("type1")
				.and("type2").as("type2")
				.and("_id").as("_id");		

		MatchOperation where = null;  //조건
		LocalDate  start_day = LocalDate .parse("2019-06-19");
		LocalDate  end_day = LocalDate .parse("2019-06-21");
		where = Aggregation.match( 
				new Criteria().andOperator(
					Criteria.where("reg_origin_date")
					.gte(start_day.atTime(0,0,0))
					.lte(end_day.atTime(0,0,0))
				)
		);

		SortOperation sort = null; //정렬
		sort = Aggregation.sort(Sort.Direction.DESC, "conv_date");

		GroupOperation groupBy = null;  //그룹핑
		groupBy= Aggregation.group("conv_date","type1","type2").count().as("count")
				  .sum("number").as("num_sum");

		Aggregation agg = Aggregation.newAggregation(  //집계함수 내용 조립
				dateProjection,
				where,
				groupBy,
				sort
		);

		AggregationResults<HashMap> results = template.aggregate(agg, "대상 컬렉션", HashMap.class);  //HashMap으로 매핑
		List<HashMap> ress = results.getMappedResults();  //결과

		ress.forEach(System.out::println);	//결과 출력
    }

}

데이터가 많을수록, 몽고DB가 설치된 서버의 메모리사용량과 입출력io사용량이 늘어나게 되는데, 1천만건 정도부터는 메모리 1G, 입출력IO 점유율 30% 정도 되는 것 같다.

CPU는 그다지 사용하지는 않는 것 같다..메모리여..

 

* 2차 정리 버전

https://lts0606.tistory.com/191

 

MongoTemplate Aggregate 2 (lookup, unwind,first,last,push ..)

몽고db에서 자주 사용되는 집계함수 기능에 대해서 정리하여 보았다. 1. body 컬렉션 내용은 아래와 같다. 2. head 컬렉션 내용이다. 3. 단순 집계 기능이다. 조회, 그룹핑, 카운트 및 합계이다. 대상은 body..

lts0606.tistory.com

 

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글