select count(*) ... group by .. SQL 쿼리를 진행하려고 한다.

https://www.elastic.co/guide/en/elasticsearch/reference/1.5/_executing_aggregations.html

https://www.elastic.co/blog/intro-to-aggregations-pt-2-sub-aggregations

해결 방법은 두가지가 있다. 

- 일래스틱서치(elasticsearch)의 aggregation을 두 번 사용 (es 접속->agg요청/응답처리->es 연결 종료->es 접속 -> agg요청/응답처리->es 종료)

- 일래스틱서치(elasticsearch)의 subaggregation을 두 번 사용 (es 접속->sub agg요청/응답처리->es 연결 종료)




시간 소요 시간 테스트를 해보니. 35만건에 대해서 

aggreation을 두 번 사용하는 것은 2.6초

aggreation을 한 번 사용하는 것은 1.3초

걸렸다.


따라서, aggreation이 비싼 비용이기 때문에 aggregation을 sub aggregation을 추천한다!



자바 api 슈도 코드이다. aggreation 을 bucket으로 받아서 처리한 후,

bucket에서 aggregation을 얻어내서 처리하는 코드로 가능 (writer 개수 및 writer 정보도 다 얻어낼 수 있다.)


public List<Stat> getSubAggregation() {
List<Stat> stats = Lists.newArrayList();
QueryBuilder queryBuilder = QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), null);

TermsBuilder subTermsAgg = AggregationBuilders.terms("aggs").field("writer")
.order(Terms.Order.count(false))
.size(1000000);

TermsBuilder termsAgg = AggregationBuilders.terms("aggs").field("id")
.order(Terms.Order.count(false))
.minDocCount(100)
.subAggregation(subTermsAgg)
.size(10000);

SearchRequestBuilder searchRequest = searchClient.prepareSearch(index).setTypes(type);
searchRequest.setQuery(queryBuilder).addAggregation(termsAgg);
SearchResponse response = searchRequest.execute().actionGet();

Terms terms = response.getAggregations().get("aggs");
for (Bucket bucket : terms.getBuckets()) {
Stat stat = new Stat();
Stat.Id = bucket.getKey();
Stat.totalCount = bucket.getDocCount();
Terms subTerms = bucket.getAggregations().get("aggs");

Map<String, Long> map = Maps.newHashMap();
for (Bucket subBucket : subTerms.getBuckets()) {
map.put(subBucket.getKey(), subBucket.getDocCount());
}
stat.uniqueWriter = map.size();
stats.add(stat);
}

return stats;
}




Posted by '김용환'
,