8.2 버킷 - Bucket Aggregations

이 문서의 허가되지 않은 무단 복제나 배포 및 출판을 금지합니다. 본 문서의 내용 및 도표 등을 인용하고자 하는 경우 출처를 명시하고 김종민(kimjmin@gmail.com)에게 사용 내용을 알려주시기 바랍니다.

Bucket aggregation 은 주어진 조건으로 분류된 버킷 들을 만들고, 각 버킷에 소속되는 도큐먼트들을 모아 그룹으로 구분하는 것입니다. 각 버킷 별로 포함되는 도큐먼트의 개수는 doc_count 값에 기본적으로 표시가 되며 각 버킷 안에 metrics aggregation 을 이용해서 다른 계산들도 가능합니다. 주로 사용되는 bucket aggregation 들은 Range, Histogram, Terms 등이 있습니다.

range

range 는 숫자 필드 값으로 범위를 지정하고 각 범위에 해당하는 버킷을 만드는 aggregation 입니다. field 옵션에 해당 필드의 이름을 지정하고 ranges 옵션에 배열로 from, to 값을 가진 오브젝트 값을 나열해서 범위를 지정합니다. 다음은 passangers 값이 각각 1000 미만, 1000~4000 사이, 4000 이상 인 버킷들을 생성하는 예제입니다.

request
response
request
range aggs 를 이용해서 passangers 필드의 값을 버킷으로 구분
GET my_stations/_search
{
"size": 0,
"aggs": {
"passangers_range": {
"range": {
"field": "passangers",
"ranges": [
{
"to": 1000
},
{
"from": 1000,
"to": 4000
},
{
"from": 4000
}
]
}
}
}
}
response
range aggs 를 이용해서 passangers 필드의 값을 버킷으로 구분한 결과
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 10,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"passangers_range" : {
"buckets" : [
{
"key" : "*-1000.0",
"to" : 1000.0,
"doc_count" : 1
},
{
"key" : "1000.0-4000.0",
"from" : 1000.0,
"to" : 4000.0,
"doc_count" : 3
},
{
"key" : "4000.0-*",
"from" : 4000.0,
"doc_count" : 6
}
]
}
}
}

각각의 버킷을 구분하는 key 값은 "from-to" 형태로 생성됩니다. 위 쿼리 결과에서 각각의 "*-1000.0", "1000.0-4000.0", "key" : "4000.0-*" 버킷에 속한 도큐먼트의 개수가 1, 3, 6개 인 것을 확인할 수 있습니다.

aggs 에 설정한 from이상 즉 버킷에 포함이고 to미만 으로 버킷에 포함하지 않습니다. 예를 들어 필드 값이 200 인 도큐먼트는 "key" : "100-200" 버킷에는 포함되지 않고 "key" : "200-300" 버킷에는 포함됩니다.

histogram

histogram 도 range 와 마찬가지로 숫자 필드의 범위를 나누는 aggs 입니다. 앞에서 본 range 는 from 과 to 를 이용해서 각 버킷의 범위를 지정했습니다. histogram 은 from, to 대신 interval 옵션을 이용해서 주어진 간격 크기대로 버킷을 구분합니다. 다음은 passangers 필드에 간격이 2000인 버킷들을 생성하는 예제입니다.

request
response
request
histogram aggs 를 이용해서 passangers 필드의 값을 버킷으로 구분
GET my_stations/_search
{
"size": 0,
"aggs": {
"passangers_his": {
"histogram": {
"field": "passangers",
"interval": 2000
}
}
}
}
response
histogram aggs 를 이용해서 passangers 필드의 값을 버킷으로 구분한 결과
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 10,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"passangers_his" : {
"buckets" : [
{
"key" : 0.0,
"doc_count" : 2
},
{
"key" : 2000.0,
"doc_count" : 2
},
{
"key" : 4000.0,
"doc_count" : 4
},
{
"key" : 6000.0,
"doc_count" : 2
}
]
}
}
}

각각의 버킷을 구분하는 key 에는 값의 최소값이 표시됩니다. 위 예제에서 0, 2000, 4000, 6000 인 버킷들이 생성되었고 각 버킷들에 포함되는 도큐먼트 개수가 표시된 것을 볼 수 있습니다. key 값은 range 와 마찬가지로 key 로 지정된 값이 버킷에 이상(포함) / 미만(포함하지 않음) 으로 지정됩니다.

date_range, date_histogram

rangehistogram aggs 처럼 숫자 외에도 날짜 필드를 이용해서 범위별로 버킷의 생성이 가능합니다. 이 때 사용되는 date_range, date_histogram aggs 들은 특히 시계열 데이터에서 날짜별로 값을 표시할 때 매우 유용합니다. date_rangeranges 옵션에 {"from": "2019-06-01", "to": "2016-07-01"} 와 같이 입력하며 date_histograminterval 옵션에 day, month, week 와 같은 값들을 이용해서 날짜 간격을 지정할 수 있습니다. 다음은 date_histogram 으로 date 필드를 1개월 간격으로 구분하는 예제입니다.

request
response
request
date_histogram 을 이용해서 date 값을 1개월 간격의 버킷으로 구분
GET my_stations/_search
{
"size": 0,
"aggs": {
"date_his": {
"date_histogram": {
"field": "date",
"interval": "month"
}
}
}
}
response
date_histogram 을 이용해서 date 값을 1개월 간격의 버킷으로 구분한 결과
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 10,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"date_his" : {
"buckets" : [
{
"key_as_string" : "2019-06-01T00:00:00.000Z",
"key" : 1559347200000,
"doc_count" : 2
},
{
"key_as_string" : "2019-07-01T00:00:00.000Z",
"key" : 1561939200000,
"doc_count" : 2
},
{
"key_as_string" : "2019-08-01T00:00:00.000Z",
"key" : 1564617600000,
"doc_count" : 2
},
{
"key_as_string" : "2019-09-01T00:00:00.000Z",
"key" : 1567296000000,
"doc_count" : 3
},
{
"key_as_string" : "2019-10-01T00:00:00.000Z",
"key" : 1569888000000,
"doc_count" : 1
}
]
}
}
}

date_histogram의 결과에서는 버킷별로 key 에 시작 날짜가 epoch_millis 값으로 표시됩니다. 그리고 key_as_stringISO8601 형태로도 함께 표시됩니다.

7.2 버전 부터는 interval 옵션이 사용 종료 권장(depricated) 되고 대신 fixed_intervalcalendar_interval 으로 나누어 지게 되었습니다. year, quarter, month, week, 같은 달력 기준의 값은 "calendar_interval" : "month" 로 입력을 하고, 30일 처럼 정확히 구분되는 날짜들은 "fixed_interval" : "30d" 로 지정을 해야 합니다.

terms

앞에서 살펴 본 (date_)range, histogram 은 모두 숫자, 날짜를 가지고 구간을 나누는 aggregation 이었습니다. terms aggregation 은 keyword 필드의 문자열 별로 버킷을 나누어 집계가 가능합니다. keyword 필드 값으로만 사용이 가능하며 분석된 text 필드는 일반적으로는 사용이 불가능합니다. 다음은 my_stations 인덱스에서 station.keyword 필드를 기준으로 버킷들을 만드는 예제입니다.

request
response
request
terms 을 이용해서 station 값을 별로 버킷 생성
GET my_stations/_search
{
"size": 0,
"aggs": {
"stations": {
"terms": {
"field": "station.keyword"
}
}
}
}
response
terms 을 이용해서 station 값을 별로 버킷 생성한 결과
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 10,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"stations" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "강남",
"doc_count" : 5
},
{
"key" : "불광",
"doc_count" : 1
},
{
"key" : "신촌",
"doc_count" : 1
},
{
"key" : "양재",
"doc_count" : 1
},
{
"key" : "종각",
"doc_count" : 1
},
{
"key" : "홍제",
"doc_count" : 1
}
]
}
}
}

terms aggregation 에는 field 외에도 가져올 버킷의 개수를 지정하는 size 옵션이 있으며 디폴트 값은 10 입니다. 인덱스의 특정 keyword 필드에 있는 모든 값들을 종류별로 버킷을 만들면 가져와야 할 결과가 매우 많기 때문에 먼저 도큐먼트 개수 또는 주어진 metrics 연산 결과가 가장 많은 버킷 들을 샤드별로 계산해서 상위 몇개의 버킷들만 coordinate 노드로 가져오고, 그것들을 취합해서 결과를 나타냅니다. 이 과정은 검색의 query 그리고 fetch 과정과 유사합니다.