select count(*) ... group by .. SQL 쿼리를 진행하려고 한다.
https://www.elastic.co/guide/en/elasticsearch/reference/1.5/_executing_aggregations.html
해결 방법은 두가지가 있다.
- 일래스틱서치(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;
}
'Elasticsearch' 카테고리의 다른 글
[elasticsearch] groovy script 동작 가능 여부 설정 (0) | 2015.06.17 |
---|---|
[elasticsearch] 새로운 필드 추가하기 / 데이터 저장하기 (0) | 2015.06.16 |
[elasticsearch] count (개수 계산) api (0) | 2015.06.03 |
[elasticsearch] Query vs Filter (0) | 2015.06.01 |
hit (0) | 2015.05.31 |