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
'몽고DB > Java 몽고DB' 카테고리의 다른 글
몽고DB 트랜잭션을 위한 리플리카 셋, 적용 테스트(Mongodb transaction, Mongodb replica set) (5) | 2019.11.26 |
---|---|
Java Mongodb 연동, Java 몽고db 연동 (4.0이상 버전) (0) | 2019.11.26 |
MongoTemplate Aggregate 2 (lookup, unwind,first,last,push ..) (0) | 2019.09.06 |
MongoTemplate Aggregate 사용간 파싱 버그 (0) | 2019.07.19 |
스프링(전자정부), 몽고DB와의 연동 (몽고DB 터널링, Mongodb Ternering, Mongodb ssh) (14) | 2019.05.09 |
댓글