
[ 엘라스틱 서치 바이블 ] 공부한 후 정리한 내용 입니다!!!
3. 검색 API
- 엘라스틱의 핵심인 검색 엔진
(3-1) 검색 대상 지정
- GET, POST 메서드를 사용하며 _search 옵션 호출
- 인덱스 미지정시 전체 인덱스에 대해 검색
- 인덱스 명 지정시 와일드 카드 가능, 및 콤마를 구분해 여러 검색 대상 지정 가능
### 검색 대상 지정 테스트
curl -XGET "http://192.168.56.10:9200/*sy*,my_index2/_search?pretty"
>>> sy가 포함된 인덱스 + my_index2 검색 ( 지정 인덱스 모든 문서 hit )
(3-2) 쿼리 DSL 검색, 쿼리 문자열 검색
- 검색 요청 본문에 엘라스틱서치 전용 쿼리 기술하는 방법, 요청 주소줄에 q라는 매개변수로 검색하는 두 방법이 있음
- 두가지 방법 혼용은 안됨 ( q 매개변수 우선 작동 )
쿼리 DSL 검색
### 쿼리 DSL 검색
curl -XGET "http://192.168.56.10:9200/my_index/_search?pretty" -H "Content-Type: application/json" -d \
'{
"query": {"match": {"title": "hello"}}
}'

- _source를 해당 쿼리를 통한 유사도 확인 가능
쿼리 문자열 검색
- 간단한 요청을 이용하는 경우 사용
### 쿼리 문자열 검색 테스트
curl -XGET "http://192.168.56.10:9200/my_index/_search?pretty&q=title:hello"
### 쿼리 문자열 문법
1) _search?q=hello : 전체 필드 대상 검색
2) _search?q=title:hello : 지정 필드 대상 검색 ( title 필드 대상 )
3) _search?q=_exists_:title : 특정 필드 존재하는 문서 검색
4) _search?q=[필드 명]:[시작 TO 끝] : 지정필드 시작 ~ 끝 사이 문서 검색
[] 는 경계값 포함 {} 는 경계값 포함 X
경계값 없는 경우 * 사용
ex)
date:[2024-12-01 TO 2024-12-19] : 2024-12-01 <= date 필드 데이터 <= 2024-12-19
date:{2024-12-01 TO 2024-12-19} : 2024-12-01 < date 필드 데이터 < 2024-12-19
date:[* TO 2024-12-19] : date 필드 데이터 <= 2024-12-19
date:[2024-12-01 TO *] : 2024-12-01 <= date 필드 데이터
5) 질의에 와일드카드, ? 사용
_search?q=title:hello*
와일드 카드 포함 쿼리는 매우 느리며 위험.. ㅠㅠ
6) 쿼리 and, or 연산 적용
_search?q=_exists_:type%20AND%20title:hello
_search?q=title:syoung%20OR%20title:hello
(3-3) match_all 쿼리
- 모든 문서를 매치하는 쿼리 ( query 부분 비워드면 기본값으로 지정되는 쿼리 )
### match_all 쿼리 문법
curl -XGET "http://192.168.56.10:9200/my_index/_search?pretty" -H "Content-Type: application/json" -d \
'{
"query": {"match_all": {}}
}'
(3-4) match 쿼리
- 필드 내용이 질의어와 매치되는 문서 찾는 쿼리
- 필드 type이 text이면 질의어도 애널라이저로 분석
- 애널라이저 분석의 경우 각 텀은 or 조건으로 매칭 하는데 operartor를 and로 지정하며 모든 텀이 매치된 문서만 검색되도록 변경 가능
### match 쿼리 문법
curl -XGET "http://192.168.56.10:9200/[인덱스 명]/_search?pretty" -H "Content-Type: application/json" -d \
'{
"query": {"match": {"fieldName": {"query": "test query sentence", "operator": "and"}}}
}'
(3-5) term 쿼리
- 지정한 필드 값이 질의어와 정확히 일치하는 문서를 찾는 쿼리
- text 타입 필드 대상 term 쿼리를 사용하는 경우 : 분석 결과 생성된 단일 텀과 노멀라이저를 거친 질의어가 완전히 같은 경우 검색
### term 쿼리 문법
curl -XGET "http://192.168.56.10:9200/my_index/_search?pretty" -H "Content-Type: application/json" -d \
'{
"query": {"term": {"title.keyword": {"value": "hello"}}}
}'
(3-6) terms 쿼리
- 지정 필드 값이 질의어와 정확이 일치하는 문서 찾는 쿼리 ( 질의어 여러 개 지정 가능!! )
- 하나 이상의 질의어가 일치시 검색 결과 포함
### terms 쿼리 문법
curl -XGET "http://192.168.56.10:9200/my_index/_search?pretty" -H "Content-Type: application/json" -d \
'{
"query": {"terms": {"title.keyword": ["hello", "syoung"]}}
}'
>>> title 필드값이 hello, syoung 문서 검색 ( 둘중 하나 이상 일치시 검색 )
(3-7) range 쿼리
- 필드 값이 범위 내에 있는 문서 검색
- 범위는 gt, lt, gte, lte 이용
- gt 필드 값 lt : < 필드 값 <
- gte 필드 값 lte : <= 필드 값 <=
- 문자열 필드 대상의 range 쿼리는 부하가 큰 쿼리 ( 초심히 사용 )
### range 쿼리 문법
curl -XGET "http://192.168.219.20:9200/my_index2/_search?pretty" -H "Content-Type: application/json" -d \
'{
"query": {"range": {"point": {"gte": 500, "lte": 1800}}}
}'
(3-8) prefix 쿼리
- 필드 값이 지정한 질의어로 시작하는 문서 찾는 쿼리
### prefix 쿼리 문법
curl -XGET "http://192.168.219.20:9200/my_index2/_search?pretty" -H "Content-Type: application/json" -d \
'{
"query": {"prefix": {"park_name": {"value": "sy"}}}
}'
- prefix도 무거운 쿼리.. 서비스 성 호출로 사용하려면 매핑에 index_prefixes 설정 넣는 방법 사용
### 매핑에 index_prefixes 설정 넣기
curl -XPUT "http://192.168.219.20:9200/prefix_mapping_test?pretty" -H "Content-Type: application/json" -d \
'{
"mappings": {
"properties": {
"prefixField": {"type": "text", "index_prefixes": {"min_chars": 3, "max_chars": 5}}
}
}
}'
>>> es 문서 색인시 min_chars ~ max_chars 사이 prefix를 미리 별도로 색인
>>> 색인에서 손해보는 대신 prefix 쿼리 성능 높이는 방법
(3-9) exists 쿼리
- 지정한 필드를 포함한 문서 검색
### exists 쿼리
curl -XGET "http://192.168.219.20:9200/my_index2/_search?pretty" -H "Content-Type: application/json" -d \
'{
"query": {
"exists": {"field": "park_name"}
}
}'
(3-10) bool 쿼리
- 여러 쿼리 조합하여 검색하는 쿼리 ( 4가지 종류 사용 )
- must, filter 조건절에 들어간 하위 쿼리는 모두 AND 조건으로 만족해야 검색 결과 포함
- must_not 조건절에 들어간 쿼리를 만족하는 문서는 최종 검색결과 제외
- should 조건절에 들어간 쿼리는 minimum_should_match 지정 갯수 이상의 하위 쿼리를 만족하는 문서가 검색 결과에 포함 ( should 조건은 OR 조건 )
### bool 쿼리 문법
curl -XGET "http://192.168.219.20:9200/[인덱스 명]/_search?pretty" -H "Content-Type: application/json" -d \
'{
"query": {
"bool": {
"must": [
~~
],
"must_not": [
~~
],
"filter": [
~~
],
"should": [
~~
]
"minimum_should_match": 1
}
}
}'
쿼리 문맥과 필터 문맥
- 필터 문맥 : 단순 조건을 만족하는 여부만 따지는 검색 과정 ( bool filter, must_not 조건, exists, range, constatnt_socre.. )
- 쿼리 문맥 : 검색 조건에 유사도 점수를 매기는 검색 과정 ( bool must, should 조건, match, term.. )
- 유사도 점수를 매길 필요가 없는 조건이면 필터 문맥이 성능상 유리 ( 점수 계산 비용 아낌, 쿼리 캐시에 저장해 재활용 가능 )
쿼리 수행 순서
- es는 검색요청 받으면 내부적으로 비용을 추정하고 유리할 것이라 생각되는 부분 먼저 수행
- 문서 참, 거짓을 판별하는 과정을 거친 후 점수 계산 ( 필터 문맥 쿼리 점수 계산 하지 않음 )
- 세부 쿼리 실행 순서를 원하는 대로 하려면 커스텀 쿼리 만들어야됨
(3-11) constant_score 쿼리
- filter 부분에 지정한 쿼리를 필터 문맥에서 검색하는 쿼리
- 해당 쿼리 매치된 문서 유사도 점수는 1로 지정
### constant_score 쿼리 테스트
curl -XGET "http://192.168.56.10:9200/[인덱스 명]/_search?pretty" -H "Content-Type: application/json" -d \
'{
"query": {
"constant_score": {"filter": { ~~~ }}
}
}'
(3-12) 검색 api 매개변수
라우팅 : 라우팅을 지정하여 성능 향상 ( routing=[라우팅 명] )
explain : 검색 점수가 어떻게 계산되는지 설명 ( explain=true )
search_type : 점수 계산 샤드 레벨 지정
- query_then_fetch >>> 기본 설정, 각 샤드에서 점수 계산 끝냄
- dfs_query_then_fetch >>> 모든 샤드 정보를 모아 유사도 점수 계산 ( 점수 향상되지만 검색 성능 떨어짐 ㅠㅠ )
(3-13) 검색 결과 정렬
- 요청 본문에 sort를 지정해 검색 결과 정렬
- 디폴트는 오름차순 ( desc : 내림차순, asc: 오름차순 )
- text 타입 필드는 fielddata를 true로 지정시 정렬 사용 가능, but.. 역색인 정보를 메모리에 올려야되서 oom 야기... 위험
- 필드 이름 이외 _score, _doc로 정렬 지정 가능 ( _score : 유사도 점수, _doc : 문서 번호 )
- 정렬 옵션에 _score가 포함되지 않으면 점수 계산 안함
### 검색 정렬 문법
curl -XGET "http://192.168.56.10:9200/my_index/_search?pretty" -H "Content-Type: application/json" -d \
'{
"sort": [{"age": "desc"}]
}'
(3-14) 페이지네이션
from , size
- from : 몇 번쨰 문서부터 결과 반환할지
- size : 몇 개의 문서 반환할 것인지
- from 값이 커지면 무거운 검색을 수행 해야됨 ㅠㅜ ( from + size 합이 1만이 넘어가는 검색은 수행 불가, 윈도우 크기 늘려줘야됨 )
- 특정 시점의 데이터를 검색하려면 페이지네이션 해야됨 ( 두 검색 요청 사이에 인덱스 상태가 달라질수 있음 )
### from, size 테스트
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_ecommerce/_search?pretty" -H "Content-Type: application/json" -d \
'{
"from": 10,
"size": 1
}'
>>> 10번쨰 문서부터 하나 검색
scroll
- 검색 조건 매칭 문서 모두 순회
- 순회하는 동안 최초 검색 문맥 유지 ( 검색 문맥 유지 시간 지정 )
### scroll 테스트
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_ecommerce/_search?pretty&scroll=1m" -H "Content-Type: application/json" -d \
'{
"size": 500
}' | grep _scroll_id > /data/work/scroll_id.txt
curl -XGET "http://192.168.56.10:9200/_search/scroll?pretty" -H "Content-Type: application/json" -d \
'{
"scroll_id": "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFlBkVW1OeUVOUjhtSmgtLTFKN1cyWXcAAAAAAAAB0BZVbUppUExYZFNJNnVFR2Y3alc3enFn",
"scroll": "1m"
}'
>>> 스크롤 id 로 검색을 반복
>>> 더 이상 문서가 반환되지 않으면 모든 검색 완료
### 검색 문맥 명시적 제거
curl -XDELETE "http://192.168.56.10:9200/_search/scroll?pretty" -H "Content-Type: application/json" -d \
'{
"scorll_id": "스크롤id"
}'
search_after
- 사용자가 검색 결과를 요청하고 결과에 페이지네이션 제공하는 용도 사용
- sort를 지정해야 하며 동일 정렬 값이 등장할 수 없게 1개 이상의 동점 제거 필드 지정
- 동점 제거용 필드는 doc_values가 켜져있는 필드로 지정하는게 좋음
### 페이지네이션 search_after 테스트
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_ecommerce/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 20,
"query": {
"term": {
"currency": {"value": "EUR"}
}
},
"sort": [{"order_date": "desc"}, {"order_id": "asc"}]
}'
>>> 응답 sort 값
"sort" : [
1736627990000,
"591924"
]
### 첫 검색 응답으로 sort 기준값을 가져와 요청 본문 search_after 필드에 해당 값을 넣어 다음 요청 검색
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_ecommerce/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 20,
"query": {
"term": {
"currency": {"value": "EUR"}
}
},
"search_after": [1736627990000, "591924"],
"sort": [{"order_date": "desc"}, {"order_id": "asc"}]
}'
- 동점 제거용 필드 지정했더라도 인덱스 상태가 변하는 중 페이지네이션 과정이면 변동 사항 발생
- point in time API를 사용해 search_after 사용시 인덱스 상태를 특정 시점으로 고정
point in time API
- search_after 페이지네이션 사용시 인덱스 상태를 고정
- keep_alive 매개변수에 상태유지 시간 지정
- 별도 정렬을 지정할 필요 없음 ( pit는 _shard_doc를 사용해 문서의 물리적 저장 위치에 따라 결과를 고유하게 정렬 )
- 정렬을 지정하게 되면 _shard_doc는 맨 마지막에 자동 추가
### point in time API 사용 테스트 ( 검색 대상 상태 고정 )
curl -XPOST "http://192.168.56.10:9200/kibana_sample_data_ecommerce/_pit?keep_alive=1m"
>>> 응답으로 pit id 값 반환
{"id":"697qAwEca2liYW5hX3NhbXBsZV9kYXRhX2Vjb21tZXJjZRZpX1djQ1M4UlJiYUY5dVRMakRoVnBnABZCNk42MFJDRVJ4LUtyS0Z3ZG9ZQy1nAAAAAAAAAAAEFnRZX3loQ1E1UTJLTzhPVExMUElyUUEAARZpX1djQ1M4UlJiYUY5dVRMakRoVnBnAAA="}
### 얻은 pit id 값을 이용해 검색 대상을 고정
### 검색시 인덱스 지정 안함, pit id를 통해 검색 대상 지정하기 때문
curl -XGET "http://192.168.56.10:9200/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 20,
"query": {
"term": {
"currency": {"value": "EUR"}
}
},
"pit": {
"id":"697qAwEca2liYW5hX3NhbXBsZV9kYXRhX2Vjb21tZXJjZRZpX1djQ1M4UlJiYUY5dVRMakRoVnBnABZCNk42MFJDRVJ4LUtyS0Z3ZG9ZQy1nAAAAAAAAAAAGFnRZX3loQ1E1UTJLTzhPVExMUElyUUEAARZpX1djQ1M4UlJiYUY5dVRMakRoVnBnAAA=",
"keep_alive": "1m"
},
"sort": [{"order_date": "desc"}]
}'
>>> 응답으로 sort 값 리턴
"sort" : [
1736627990000,
4290
]
### 첫 검색 결과를 통해 받은 sort 값을 search_after필드 값으로 지정해 search_after 페이지네이션 수행
curl -XGET "http://192.168.56.10:9200/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 20,
"query": {
"term": {
"currency": {"value": "EUR"}
}
},
"pit": {
"id":"697qAwEca2liYW5hX3NhbXBsZV9kYXRhX2Vjb21tZXJjZRZpX1djQ1M4UlJiYUY5dVRMakRoVnBnABZCNk42MFJDRVJ4LUtyS0Z3ZG9ZQy1nAAAAAAAAAAAGFnRZX3loQ1E1UTJLTzhPVExMUElyUUEAARZpX1djQ1M4UlJiYUY5dVRMakRoVnBnAAA=",
"keep_alive": "1m"
},
"search_after": [1736627990000, 4290],
"sort": [{"order_date": "desc"}]
}'
### point in time API 명시적 삭제 ( pit_id 값을 지정해 명시적 삭제 가능 )
curl -XDELETE "http:///192.168.56.10:9200/_pit" -H "Content-Type: applicatoin/json" -d \
'{
"id" :~~~~
}'
4. 집계
- 검색을 수행한 후 >>> 집계를 수행하여 데이터 기반 문제 해결
(4-1) 집계 기본
- es 집계는 검색의 연장선 ( 검색으로 데이터를 추려낸 후 >> 집계를 통해 인사이트 제공 )
- 집계 요청 상세는 aggs 필드 밑에 기술
- 여러 집계 요청할수 있어 구분을 위한 이름을 붙여야됨
- es 집계는 크게 메트릭, 버킷, 파이프라인 집계로 구분
### 엘라스틱 집계 테스트
### sum 집계 : 검색 문서 지정한 필드 값을 모두 합친 값 반환
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_ecommerce/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 0,
"query": {"term": {"currency": {"value": "EUR"}}},
"aggs": {
"my-sum-agg-name": {
"sum": {
"field": "taxless_total_price"
}
}
}
}'
>>> 집계시 size는 0으로 설정하여 성능 이득 취할수 있음 ( 문서 내용 수집 X, 점수 계산 X )
(4-2) 메트릭 집계
- 검색 결과에 대한 산술적인 연산 수행하는 집계
1) avg, max, min, sum 집계
- 검색 문서 대상 지정한 필드 값을 평균, 최대값, 최솟값, 합 으로 반환
### avg, max, min, sum 집계 ( 메트릭 집계 )
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_ecommerce/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 0,
"query": {"term": {"currency": {"value": "EUR"}}},
"aggs": {
"my-avg-name": {"avg": {"field": "taxless_total_price"}},
"my-max-name": {"max": {"field": "taxless_total_price"}},
"my-sum-name": {"sum": {"field": "taxless_total_price"}}
}
}'
>>> 집계 요청 필드에 원하는 집계 요청 지정 ( avg, max, min, sum )
2) stats 집계
- 지정한 필드의 평균, 최대, 최소, 합, 갯수 결과를 모두 반환
### stats 집계 ( 메트릭 집계 )
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_ecommerce/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 0,
"query": {"term": {"currency": {"value": "EUR"}}},
"aggs": {
"my-stats-name": {"stats": {"field": "taxless_total_price"}}
}
}'
>>> 지정 필드 평균, 최대, 최소, 합, 갯수 값을 응답
"aggregations" : {
"my-stats-name" : {
"count" : 4675,
"min" : 6.98828125,
"max" : 2250.0,
"avg" : 75.05542864304813,
"sum" : 350884.12890625
}
}
3) cardinality 집계
- 지정 필드가 가진 고유한 값 갯수를 반한
- 결과는 hyperloglog++ 알고리즘 사용해 추정한 근사값
- 정확도 조절을 위해 precision_threshold 사용 ( 기본값은 3000, 값을 높이면 정확도 올라가지만 메모리 사용 증가 )
- precision_threshold > cardinality : 정확도가 충분히 높음
- precision_threshold < cardinality : 정확도가 떨어짐 ( 조정 필요 )
### cardinality 집계 ( 메트릭 집계 )
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_ecommerce/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 0,
"query": {"term": {"currency": {"value": "EUR"}}},
"aggs": {
"my-cardinlity-name": {
"cardinality": {"field": "customer_id", "precision_threshold": 3000}
}
}
}'
>>> 지정 필드 고유값 반환
"aggregations" : {
"my-cardinlity-name" : {
"value" : 46
}
}
(4-3) 버킷 집계
- 검색한 문서를 특정 기준으로 쪼개 여러 부분으로 나눔
- 나눠진 부분을 버킷이라 하며 각 버킷 별도로 하위 집계 수행
- 여러 버킷으로 나눈 뒤 하위 집계 수행하는 것이 버킷 집계 핵심, but... 깊이가 너무 깊어지면 성능에 문제 ㅠㅠ
1) range 집계
- 지정한 필드값 기준으로 문서를 원하는 버킷 구간으로 나눔
- 버킷 구간을 나눌 필드와 기준 값을 요청 본문에 지정
- range 밑에 aggs 하나 더 추가하여 하위 집계 지정 ( 미 지정시 doc_count 까지 세고 끝냄 )
### range 집계 ( 버킷 집계 )
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_flights/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 0,
"query": {"match_all": {}},
"aggs": {
"distance-kilo-range": {
"range": {
"field": "DistanceKilometers",
"ranges": [{"to": 5000},{"from": 5000, "to": 10000},{"from": 10000}]
},
"aggs": {
"stats-tickete-price": {
"stats": {"field": "AvgTicketPrice"}
}
}
}
}
}'
>>> DistanceKilometers 필드 range 기준 으로 버킷 생성후
>>> 각 버킷 AvgTicketPrice 필드 stats 집계
2) date_range 집계
- date 타입 필드 대상으로 사용
### date_range 집계 ( 버킷 집계 )
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_ecommerce/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 0,
"query": {"term": {"currency": {"value": "EUR"}}},
"aggs": {
"date-range-aggs": {
"date_range": {
"field": "order_date",
"ranges": [{"to":"now-10d/d"},{"from": "now-10d/d", "to": "now"},{"from": "now"}]
},
"aggs": {
"stats-taxless_total_price": {
"stats": {"field": "taxless_total_price"}
}
}
}
}
}'
- now 가 포함된 집계는 캐시에 올라가지 않음 ( 동일 집계 요청은 요청 본문이 동일한가로 구문하기 떄문 )
3) histogram 집계
- range와 유사 하지만 경계값 기준을 직접 지정하는 것이 아닌 간격 ( interval ) 으로 지정
- 위치 조정 하지 않으면 0을 기준으로 interval, offset을 사용해 위치 지정 가능
- min_doc_count를 지정해 버킷 내 문서 개수가 일정 이하인 버킷 결과에서 제외 가능
### histogram 집계 ( 버킷 집계 )
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_flights/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 0,
"query": {"match_all": {}},
"aggs": {
"my-histogram": {
"histogram": {
"field": "DistanceKilometers",
"interval": 1000
},
"aggs": {
"stats-ticket_price": {
"stats": {"field": "AvgTicketPrice"}
}
}
}
}
}'
### offset을 사용해 interval 위치 지정 가능
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_flights/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 0,
"query": {"match_all": {}},
"aggs": {
"my-histogram": {
"histogram": {
"field": "DistanceKilometers",
"interval": 1000,
"offset": 50
},
"aggs": {
"stats-ticket_price": {
"stats": {"field": "AvgTicketPrice"}
}
}
}
}
}'
### min_doc_count를 지정해 버킷 문서 갯수가 1000 이하인 버킷 결과에서 제외
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_flights/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 0,
"query": {"match_all": {}},
"aggs": {
"my-histogram": {
"histogram": {
"field": "DistanceKilometers",
"interval": 1000,
"min_doc_count": 1000
},
"aggs": {
"stats-ticket_price": {
"stats": {"field": "AvgTicketPrice"}
}
}
}
}
}'
4) date_histogram 집계
- histogram 집계와 유사하지만 date 타입 필드 기준으로 사용
- calendar_interval, fixed_interval 사용
- offset과 min_doc_count 설정 지정 가능
### date_histogram 집계 ( 버킷 집계 )
### calendar_interval : 1분, 1시간, 하루, 한달 ... interval
### fixed_interval : 지정 간격 단위 interval (ex.. 3시간, 4일, 2달 ....)
### date_histogram 집계 >> calendar_interval
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_ecommerce/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 0,
"query": {"match_all": {}},
"aggs": {
"my-date-histogram": {
"date_histogram": {
"field": "order_date",
"calendar_interval": "day"
},
"aggs": {
"day_interval_max_taxless_total_price": {
"max": {"field": "taxless_total_price"}
}
}
}
}
}'
>>> calendar_interval 지정 값
minute ( 분 ), hour ( 시간 ), day ( 일 ),
month ( 월 ), quarter ( 분기 ), year ( 년 )
### date_histogram 집계 >> fixed_interval
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_ecommerce/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 0,
"query": {"match_all": {}},
"aggs": {
"my-date-histogram": {
"date_histogram": {
"field": "order_date",
"fixed_interval": "3d"
},
"aggs": {
"day_interval_max_taxless_total_price": {
"max": {"field": "taxless_total_price"}
}
}
}
}
}'
>>> 3일 간격 버킷 집계
>>> fixed_interval 지정 값
ms, s, m, h, d
5) terms 집계
- 지정 필드 기준 빈도수가 높은 term 순서대로 버킷 생성
- 버킷 생성 size를 지정하는데 각 샤드에서 size 갯수 만큼 term을 뽑아 빈도수를 센다
- 각 샤드에서 수행된 계산을 한곳에 모아 합산후 size 개수만큼 버킷을 뽑음 ( 즉, 정확하지 않을수 있음... )
- 응답에서 doc_count_error_upper_bound 필드가 오차 상한선을 나타냄 ( 해당 값이 크면 size 크기 고려, size 높이면 성능은 하락 )
- 응답에서 sum_other_doc_count는 최종적으로 버킷에 포함되지 않은 문서 수
- 모든 term에 대해 전부 순회하여 집계 원할시 composite 집계 사용하는 것이 좋음
### terms 집계 ( 버킷 집계 )
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_logs/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 0,
"query": {"match_all": {}},
"aggs": {
"terms-aggs": {
"terms": {
"field": "host.keyword",
"size": 10
}
}
}
}'
6) composite 집계
- sources로 지정된 하위 집계 버킷 모두 페이지네이션을 이용해 효율적으로 순회하는 집계
- size는 페이지네이션 한번에 몇 개의 버킷을 반환 할것인지 지정
- sources에 버킷을 조합하여 순회할 하위 집계 지정 ( 일부 집계만 지정 가능 )
- 응답의 마지막 key를 다음 요청에 넣어 페이지네이션
### composite 집계 ( 버킷 집계 )
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_logs/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 0,
"query": {"match_all": {}},
"aggs": {
"composite-aggs": {
"composite": {
"size": 100,
"sources": [
{
"terms-aggs": {
"terms": {
"field": "host.keyword"
}
}
},
{
"date-histogram-aggs": {
"date_histogram": {
"field": "timestamp",
"calendar_interval": "day"
}
}
}
]
}
}
}
}'
### composite 집계 페이지네이션
curl -XGET "http://192.168.56.10:9200/kibana_sample_data_logs/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 0,
"query": {"match_all": {}},
"aggs": {
"composite-aggs": {
"composite": {
"size": 100,
"sources": [
{
"terms-aggs": {
"terms": {
"field": "host.keyword"
}
}
},
{
"date-histogram-aggs": {
"date_histogram": {
"field": "timestamp",
"calendar_interval": "day"
}
}
}
],
"after": {
"terms-aggs": "cdn.elastic-elastic-elastic.org",
"date-histogram-aggs": 1737504000000
}
}
}
}
}'
(4-4) 파이프라인 집계
- 다른 집계 결과를 집계 대상으로 함
- buckets_path라는 인자를 통해 다른 집계 결과를 가져옴
1) cumulative_sum 집계
- 다른 집계의 값을 누적하여 합산
- buckets_path로 누적 합산할 집계명 지정
### cumulative_sum 집계 ( 파이프라인 집계 )
### 다른 집계 값을 누적합산
curl -XGET "http://192.168.219.20:9200/kibana_sample_data_ecommerce/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 0,
"query": {"match_all": {}},
"aggs": {
"daily-timestamp": {
"date_histogram": {
"field": "order_date",
"calendar_interval": "day"
},
"aggs": {
"daily-total-avg": {
"avg": {
"field": "total_quantity"
}
},
"pipeline-sum": {
"cumulative_sum": {
"buckets_path": "daily-total-avg"
}
}
}
}
}
}'
>>> date_histogram 으로 일 단위 버킷으로 나눈 뒤 하위 집계로 total_quantity 평균을 구함
>>> 이후 cumulative_sum을 하위로 두고 buckets_path를 daily-total-avg로 지정하여 평균값 누적 합산
2) max_bucket 집계
- 다른 집계 결과를 받아 가장 큰 버킷의 key와 결과값 반환하는 집계
### max_bucket 집계 ( 파이프라인 집계 )
curl -XGET "http://192.168.219.20:9200/kibana_sample_data_ecommerce/_search?pretty" -H "Content-Type: application/json" -d \
'{
"size": 0,
"query": {"match_all": {}},
"aggs": {
"daily-timestamp-bucket": {
"date_histogram": {
"field": "order_date",
"calendar_interval": "day"
},
"aggs": {
"daily-quantity-avg": {
"avg": {
"field": "total_quantity"
}
}
}
},
"max-total-quantity": {
"max_bucket": {
"buckets_path": "daily-timestamp-bucket>daily-quantity-avg"
}
}
}
}'
- 누적합은 특정 버킷내 값을 순차적으로 누적하지만 max bucket은 버킷을 종합적으로 참조하기에 date_histogram 하위에 둘수 없다..
- 즉, max_bucket 집계가 위치한 계층에서 "daily-timestamp-bucket>daily-quantity-avg" 경로를 지정해줘야함
'데이터 엔지니어( 실습 정리 ) > elasticsearch' 카테고리의 다른 글
| 6. 클러스터 운영 (1, 2, 3) (0) | 2025.01.08 |
|---|---|
| 5. 서비스 환경에 클러스터 구성 (0) | 2025.01.03 |
| 4. 데이터 다루기 (1, 2) (0) | 2024.12.14 |
| 3. 엘라스틱서치 인덱스 설계 (3, 4, 5) (0) | 2024.12.10 |
| 3. 엘라스틱서치 인덱스 설계 (1, 2) (0) | 2024.12.01 |