2019. 9. 19. 23:10ㆍSearch-Engine/Elasticsearch&Solr
이번에 다루어볼 내용은 엘라스틱서치 Aggregation API이다. 해당 기능은 SQL과 비교하면 Group by의 기능과 아주 유사하다. 즉, 문서 데이터를 그룹화해서 각종 통계 지표 만들어 낼 수 있다.
엘라스틱서치의 집계(Aggregation)
통계 분석을 위한 프로그램은 아주 많다. 하지만 실시간에 가깝게 어떠한 대용량의 데이터를 처리하여 분석 결과를 내놓은 프로그램은 많지 않다. 즉, RDBMS이나 하둡등의 대용량 데이터를 적재하고 배치등을 돌려 분석을 내는 것이 대부분이다. 하지만 엘라스틱서치는 많은 양의 데이터를 조각내어(샤딩)내어 관리하며 그 덕분에 다른 분석 프로그램보다 거의 실시간에 가까운 통계 결과를 만들어낼 수 있다.
하지만 집계기능은 일반 검색 기능보다 훨씬 더 많은 리소스를 소모한다. 성능 문제를 어느정도 효율적으로 해결하기 위해서는 캐시를 적절히 이용해야 하는 것이다. 물론 우리가 직접적으로 캐시를 조작하는 API를 사용하거나 하지는 않지만 어느정도 설정으로 조정가능하다. 그렇다면 엘라스틱서치에서 사용하는 캐시의 종류가 뭐가 있는지 간단히 알아보자.
캐시 종류 설명에 앞서 우선 엘라스틱서치의 캐시를 이용하면 질의의 결과를 캐시에 두고 다음에 동일한 요청이 오면 다시 한번 요청을 처리하는 것이 아닌 캐시에 있는 결과값을 그대로 돌려준다. 보통 캐시의 크기는 일반적으로 힙 메모리의 1%로 정도를 할당하며, 캐시에 없는 질의의 경우 성능 향상에 별다른 도움이 되지 못한다. 만약 엘라스틱서치가 사용하는 캐시 크기를 키우고 싶다면 아래와 같은 설정이 가능하다.
~/elasticsearch.yml
indices.requests.cache.size: n%
여기서 퍼센트(%)는 엘라스틱서치가 사용하는 힙메모리 중 몇 퍼센트를 나타내는 것이다. 다음은 엘라스틱서치가 사용하는 캐시 종류이다.
캐시명 | 설명 |
Node query Cache |
노드의 모든 샤드가 공유하는 LRU(Least-Recently-Used)캐시다. 캐시 용량이 가득차면 사용량이 가장 적은 데이터를 삭제하고 새로운 결과값을 캐싱한다. 쿼리 캐싱 사용여부는 elasticsearch.yml 파일에 아래 옵션을 추가한다. 기본값은 true이다. index.queries.cache.enabled: true |
Shard request Cache | 샤드는 데이터를 분산 저장하기 위한 단위로서, 사실 그 자체가 온전한 기능을 가지는 인덱스라고 볼 수 있다. 그래서 우리는 조회 기능을 특정 샤드에 요청해서 그 샤드에 있는 결과값만 얻어올 수 있는 이유가 그렇다. Shard request Cache는 바로 이 샤드에서 수행된 쿼리의 결과를 캐싱한다. 샤드의 내용이 변경되면 캐시도 삭제하기 때문에 문서 수정이 빈번한 인덱스에서는 오히려 성능 저하가 있을 수 있다. |
Field data Cache | 엘라스틱서치가 필드에서 집계 연산을 수행할 때는 모든 필드 값을 메모리에 로드한다. 이러한 이유로 엘라스틱서치에서 계산되는 집계 쿼리는 성능적인 측면에서 비용이 상당하다. Field data Cache는 집계 계산동안 필드의 값을 메모리에 보관한다. |
Aggregation API
집계 쿼리 구조
GET>http://localhost:9200/indexName/_search?size=0
1
2
3
4
5
6
7
8
9
10
|
"aggregations":{
"<aggregation_name>":{
"<aggregation_type>":{
"<aggregation_body>"
}
[,"meta":{[<meta_data_body>]}]?
[,"aggregations":{[<sub_aggregation>]+}]?
}
,[,"<aggregation_name_2>:{...}"]*
}
|
cs |
집계쿼리는 위와 같은 구조를 갖는다. 각각의 키값에 대한 설명은 직접 예제 쿼리를 통해 다루어볼 것이다. 엘라스틱서치의 집계 기능이 강력한 이유중 하나는 위의 쿼리에서 보듯 여러 집계를 중첩하여 더 고도화된 데이터를 반환할 수 있다는 점이다. 물론 중첩이 될수록 성능은 떨어지지만 더 다양한 데이터를 집계할 수 있다. 또한 URL 요청을 보면 맨뒤에 size=0이 보일 것이다. 해당 쿼리스트링을 보내지 않으면 집계 스코프 대상(query)의 결과도 노출되니 집계 결과만 보고 싶다면 size=0으로 지정해주어야 한다.
집계 Scope
집계 API의 전체 요청 JSON구조를 보면 아래와 같다.
GET> http://localhost:9200/apache-web-log/_search?size=0
1
2
3
4
5
6
7
8
9
10
11
12
13
|
{
"query":{
"match_all":{}
},
"aggs":{
"region_count":{
"terms":{
"field":"geoip.region_name.keyword",
"size":20
}
}
}
}
|
cs |
위에 query라는 필드가 하나더 존재하는데, 해당 쿼리를 통해 나온 결과값을 이용하여 집계를 내겠다라는 집계 대상이 되는 Scope를 query를 이용하여 지정한다. 참고로 aggregations는 aggs로 줄여서 필드명을 작성할 수 있다. 그렇다면 아래와 같은 쿼리는 어떠한 결과를 낼까?
GET> http://localhost:9200/apache-web-log/_search?size=0
1
2
3
4
5
6
7
8
9
10
11
|
{
"size":0,
"aggs":{
"region_count":{
"terms":{
"field":"geoip.region_name.keyword",
"size":3
}
}
}
}
|
cs |
쿼리가 생략되면 내부적으로 match_all 쿼리를 수행한다. 또한 이러한 경우도 있다. 한번의 집계 쿼리를 통해 사용자가 지정한 질의에 해당하는 문서들 집계를 수행하고 전체 문서에 대해서도 집계를 수행해야 하는 경우는 아래와 같이 글로벌 버킷을 사용하면 된다.
GET> http://localhost:9200/apache-web-log/_search?size=0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
{
"query":{
"match":{
"geoip.region_name":"California"
}
},
"aggs":{
"region_count":{
"terms":{
"field":"geoip.region_name.keyword",
"size":3
}
},
"global_aggs":{
"global":{},
"aggs":{
"all_doc_aggs":{
"terms":{
"field":"geoip.region_name.keyword",
"size":3
}
}
}
}
}
}
|
cs |
우선 region_name이 California인 질의의 결과를 이용하여 region_count라는 집계를 수행하고 이것 이외로 global_aggs 글로벌 버킷의 all_doc_aggs 집계를 전체 문서를 대상으로 한번더 수행한다. 결과는 아래와 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
{
"took": 10,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 756,
"max_score": 0,
"hits": []
},
"aggregations": {
"global_aggs": {
"doc_count": 10001,
"all_doc_aggs": {
"doc_count_error_upper_bound": 77,
"sum_other_doc_count": 5729,
"buckets": [
{
"key": "California",
"doc_count": 756
},
{
"key": "Texas",
"doc_count": 588
},
{
"key": "Virginia",
"doc_count": 424
}
]
}
},
"region_count": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "California",
"doc_count": 756
}
]
}
}
}
|
cs |
그렇다면 집계의 종류에는 무엇이 있을까?
집계 종류 | 설명 |
버킷 집계 | 쿼리 결과로 도출된 문서 집합에 대해 특정 기준으로 나눈 다음 나눠진 문서들에 대한 산술 연산을 수행한다. 이때 나눠진 문서들의 모음들이 각 버컷에 해당된다. |
메트릭 집계 | 쿼리 결과로 도출된 문서 집합에서 필드의 값을 더하거나 평균을 내는 등의 산술 연산을 수행한다. |
파이프라인 집계 | 다른 집계 또는 관련 메트릭 연산의 결과를 집계한다. |
행렬 집계 | 버킷 대상이 되는 문서의 여러 필드에서 추출한 값으로 행렬 연산을 수행한다. 이를 토대로 다양한 통계정보를 제공한다. |
이제 위의 집계 종류에 대하여 하나하나 간단히 다루어보자.
메트릭 집계
메트릭 집계(Metrics Aggregations)를 사용하면 특정 필드에 대해 합이나 평균을 계산하거나 다른 집계와 중첩해서 결과에 대해 특정 필드의 _score 값에 따라 정렬을 수행하거나 지리 정보를 통해 범위 계산을 하는 등의 다양한 집계를 수행할 수 있다. 이름에서도 알 수 있듯이 정수 또는 실수와 같이 숫자 연산을 할 수 있는 값들에 대한 집계를 수행한다.
메트릭 집계는 또한 단일 숫자 메트릭 집계와 다중 숫자 메트릭 집계로 나뉘는데, 단일 숫자 메트릭 집계는 집계를 수행한 결과값이 하나라는 의미로 sum과 avg 등이 속한다. 다중 숫자 메트릭 집계는 집계를 수행한 결과값이 여러개가 될 수 있고, stats나 geo_bounds가 이에 속한다.
-합산집계(sum)
합산집계는 단일 숫자 메트릭 집계에 해당한다.
apache 로그에 유입되는 데이터의 바이트 총합을 구하는 집계 쿼리이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
{
"aggs":{
"total_bytes":{
"sum":{
"field":"bytes"
}
}
}
}
->result
{
"took": 12,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 10001,
"max_score": 0,
"hits": []
},
"aggregations": {
"total_bytes": {
"value": 2747282505
}
}
}
|
cs |
만약 전체 데이터가 아닌 쿼리를 날려 매치되는 문서를 집계하기 위해서 특정 지역에서 유입된 apache 로그를 검색해 그 결과로 bytes 수를 총합하는 쿼리는 아래와 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
{
"query":{
"constant_score":{
"filter":{
"match":{
"geoip.city_name":"Paris"
}
}
}
},
"aggs":{
"total_bytes":{
"sum":{
"field":"bytes"
}
}
}
}
->result
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 21,
"max_score": 0,
"hits": []
},
"aggregations": {
"total_bytes": {
"value": 428964
}
}
}
|
cs |
논외의 이야기이지만, 스코어 점수가 필요없는 어떠한 검색에 constant_score 쿼리를 사용하면 성능상 이슈가 있다. 자주 사용되는 필터 쿼리는 엘라스틱 서치에서 캐시하므로 성능에 이점이 있을 수 있다. 만약 위의 쿼리에서 바이트를 KB나 MB,GB 단위로 보고 싶다면 어떻게 하면 좋을까? 사실 집계 쿼리에 데이터 크기 단위를 조정하는 기능은 없다. 하지만 script를 이용하면 집계되는 데이터를 원하는 단위로 변환이 가능하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
{
"query":{
"constant_score":{
"filter":{
"match":{
"geoip.city_name":"Paris"
}
}
}
},
"aggs":{
"total_bytes":{
"sum":{
"script":{
"lang":"painless",
"source":"doc.bytes.value"
}
}
}
}
}
|
cs |
해당 쿼리는 위의 쿼리와 동일한 결과를 내놓는다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
{
"query":{
"constant_score":{
"filter":{
"match":{
"geoip.city_name":"Paris"
}
}
}
},
"aggs":{
"total_bytes":{
"sum":{
"script":{
"lang":"painless",
"source":"doc.bytes.value / params.divice_value",
"params":{
"divice_value":1000
}
}
}
}
}
}
->result
{
"took": 30,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 21,
"max_score": 0,
"hits": []
},
"aggregations": {
"total_bytes": {
"value": 422
}
}
}
|
cs |
이렇게 스크립트를 이용하면 결과값을 일부 후처리할 수 있다. 하지만 결과가 조금이상하다. 428964/1000 인데 422가 됬다. 분명 428이 되야하는데 말이다. 그 이유는 모든 합산 값에 대한 나누기가 아니라 각 문서의 개별적인 값을 1000으로 나눈 후에 더했기 때문이다. 즉, 1000보다 작은수는 모두 0이 되어 합산이 되었다. 이 문제를 해결하기 위해서는 정수가 아닌 실수로 값을 계산해야한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
{
"query":{
"constant_score":{
"filter":{
"match":{
"geoip.city_name":"Paris"
}
}
}
},
"aggs":{
"total_bytes":{
"sum":{
"script":{
"lang":"painless",
"source":"doc.bytes.value / (double)params.divice_value",
"params":{
"divice_value":1000
}
}
}
}
}
}
->result
{
"took": 18,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 21,
"max_score": 0,
"hits": []
},
"aggregations": {
"total_bytes": {
"value": 428.96399999999994
}
}
}
|
cs |
-평균 집계(avg)
평균 집계는 단일 숫자 메트릭 집계에 해당한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
{
"query":{
"constant_score":{
"filter":{
"match":{
"geoip.city_name":"Paris"
}
}
}
},
"aggs":{
"avg_bytes":{
"avg":{
"field":"bytes"
}
}
}
}
->result
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 21,
"max_score": 0,
"hits": []
},
"aggregations": {
"total_bytes": {
"value": 20426.85714285714
}
}
}
|
cs |
-최소값 집계(min)
최소값 집계는 단일 숫자 메트릭 집계에 해당한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
{
"query":{
"constant_score":{
"filter":{
"match":{
"geoip.city_name":"Paris"
}
}
}
},
"aggs":{
"min_bytes":{
"min":{
"field":"bytes"
}
}
}
}
->result
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 21,
"max_score": 0,
"hits": []
},
"aggregations": {
"min_bytes": {
"value": 1015
}
}
}
|
cs |
최대값 집계는 aggregation_type을 max로 바꾸어주면 된다.
-개수집계(count)
개수집계는 단일 숫자 메트릭 집계에 해당한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
{
"query":{
"constant_score":{
"filter":{
"match":{
"geoip.city_name":"Paris"
}
}
}
},
"aggs":{
"count_bytes":{
"value_count":{
"field":"bytes"
}
}
}
}
->result
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 21,
"max_score": 0,
"hits": []
},
"aggregations": {
"count_bytes": {
"value": 21
}
}
}
|
cs |
-통계집계(Stats)
통계집계는 결과값이 여러 개인 다중 숫자 메트릭 집계에 해당한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
{
"query":{
"constant_score":{
"filter":{
"match":{
"geoip.city_name":"Paris"
}
}
}
},
"aggs":{
"stats_bytes":{
"stats":{
"field":"bytes"
}
}
}
}
->result
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 21,
"max_score": 0,
"hits": []
},
"aggregations": {
"stats_bytes": {
"count": 21,
"min": 1015,
"max": 53270,
"avg": 20426.85714285714,
"sum": 428964
}
}
}
|
cs |
count,min,max,avg,sum 등 한번에 모든 집계 결과를 받을 수 있다.
-확장 통계 집계(extended Stats)
확장 통계 집계는 결과값이 여러 개인 다중 숫자 메트릭 집계에 해당한다. 앞의 통계 집계를 확장해서 표준편차 같은 통계값이 추가된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
{
"query":{
"constant_score":{
"filter":{
"match":{
"geoip.city_name":"Paris"
}
}
}
},
"aggs":{
"count_bytes":{
"extended_stats":{
"field":"bytes"
}
}
}
}
->result
{
"took": 4,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 21,
"max_score": 0,
"hits": []
},
"aggregations": {
"count_bytes": {
"count": 21,
"min": 1015,
"max": 53270,
"avg": 20426.85714285714,
"sum": 428964,
"sum_of_squares": 18371748404,
"variance": 457588669.3605442,
"std_deviation": 21391.32229107271,
"std_deviation_bounds": {
"upper": 63209.501725002556,
"lower": -22355.787439288277
}
}
}
}
|
cs |
-카디널리티 집계(Cardinality)
카디널리티 집계는 단일 숫자 메트릭 집계에 해당한다. 개수 집합과 유사하게 횟수를 계산하는데, 중복된 값은 제외한 고유한 값에 대한 집계를 수행한다. 하지만 모든 문서에 대해 중복된 값을 집계하는 것은 성능에 큰 영향을 줄 수 있기에 근사치를 통해 집계한다. 근사치를 구하기 위해 HyperLogLog++ 알고리즘 기반으로 동작한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
{
"query":{
"bool":{
"must":[
{
"match":{
"geoip.country_name":"United"
}
},
{
"match":{
"geoip.country_name":"States"
}
}
]
}
},
"aggs":{
"us_city_names":{
"cardinality":{
"field":"geoip.city_name.keyword"
}
}
}
}
->result
{
"took": 25,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3974,
"max_score": 0,
"hits": []
},
"aggregations": {
"us_city_names": {
"value": 206
}
}
}
|
cs |
-백분위 수 집계(Percentiles)
역시나 근사치이고 TDigest 알고리즘을 이용한다. 카디날리티 집계와 마찬가지로 문서들의 집합 크기각 작을 수록 정확도는 높아지고, 문서의 집합이 클수록 오차범위가 늘어난다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
{
"query":{
"constant_score":{
"filter":{
"match":{
"geoip.city_name":"Paris"
}
}
}
},
"aggs":{
"bytes_percentiles":{
"percentiles":{
"field":"bytes"
}
}
}
}
->result
{
"took": 14,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 21,
"max_score": 0,
"hits": []
},
"aggregations": {
"bytes_percentiles": {
"values": {
"1.0": 1015,
"5.0": 1015,
"25.0": 3638,
"50.0": 6146,
"75.0": 50662.75,
"95.0": 53270,
"99.0": 53270
}
}
}
}
|
cs |
아래와 같이 백분율을 명시할 수도 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
{
"query":{
"constant_score":{
"filter":{
"match":{
"geoip.city_name":"Paris"
}
}
}
},
"aggs":{
"bytes_percentiles":{
"percentiles":{
"field":"bytes",
"percents":[0,10,20,30,40,50,60,70,80,90,100]
}
}
}
}
->result
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 21,
"max_score": 0,
"hits": []
},
"aggregations": {
"bytes_percentiles": {
"values": {
"0.0": 1015,
"10.0": 1015,
"20.0": 3638,
"30.0": 4629.2,
"40.0": 4877,
"50.0": 6146,
"60.0": 17147,
"70.0": 37258.399999999994,
"80.0": 52315,
"90.0": 52697,
"100.0": 53270
}
}
}
}
|
cs |
-백분위 수 랭크 집계
위의 랭크 집계와는 달리 특정 값을 주고 어느 백분위 범위에 속하는지를 결과값으로 돌려준다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
{
"query":{
"constant_score":{
"filter":{
"match":{
"geoip.city_name":"Paris"
}
}
}
},
"aggs":{
"bytes_percentiles_rank":{
"percentile_ranks":{
"field":"bytes",
"values":[4000,6900]
}
}
}
}
->result
{
"took": 5,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 21,
"max_score": 0,
"hits": []
},
"aggregations": {
"bytes_percentiles_rank": {
"values": {
"4000.0": 26.592105768861217,
"6900.0": 53.03370689244701
}
}
}
}
|
cs |
-지형 경계 집계
지형 좌표를 포함하고 있는 필드에 대해 해당 지역 경계 상자를 계산하는 메트릭 집계다. 해당 집계를 사용하기 위해서는 계산하려는 필드의 타입이 geo_point여야 한다.
필드 매핑타입이다.
해당 필드에 들어간 값의 예제이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
{
"aggs":{
"viewport":{
"geo_bounds":{
"field":"geoip.location",
"wrap_longitude":true
}
}
}
}
->result
{
"took": 14,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 10001,
"max_score": 0,
"hits": []
},
"aggregations": {
"viewport": {
"bounds": {
"top_left": {
"lat": 69.34059997089207,
"lon": -159.76670005358756
},
"bottom_right": {
"lat": -45.88390002027154,
"lon": 176.91669998690486
}
}
}
}
}
|
cs |
추후 키바나에서 이러한 지형집계로 시각화를 할 수 있다.
-지형 중심 집계
지형 경계 집계 범위에서 정가운데의 위치를 반환한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
{
"aggs":{
"centroid":{
"geo_centroid":{
"field":"geoip.location"
}
}
}
}
->result
{
"took": 10,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 10001,
"max_score": 0,
"hits": []
},
"aggregations": {
"centroid": {
"location": {
"lat": 38.715619301146354,
"lon": -22.189867686554656
},
"count": 9993
}
}
}
|
cs |
여기까지 메트릭 집계에 대해 간단히 다루어봤다. 글이 길어져 다음 포스팅에 이어서 집계 API를 다루어보도록 한다.
'Search-Engine > Elasticsearch&Solr' 카테고리의 다른 글
Elasticsearch - Aggregation API(엘라스틱서치 집계,파이프라인(Pipeline Aggregations) 집계) -3 (0) | 2019.09.20 |
---|---|
Elasticsearch - Aggregation API(엘라스틱서치 집계,버킷(Bucket Aggregations) 집계) -2 (1) | 2019.09.20 |
Elasticsearch - Rest High Level Client를 이용한 Index Template 생성 (0) | 2019.06.27 |
ELK Stack - Logstash(로그스태시)를 이용한 로그 수집 (1) | 2019.06.26 |
ELK Stack - Filebeat(파일비트)란? 간단한 사용법 (1) | 2019.06.17 |