Elasticsearch ES|QL
본 포스팅은 2023년 11월 22일, Elasticsearch 8.11.1 버전 기준으로 작성되었습니다.
ES|QL이 필요한 이유
Elasticsearch는 기존에도 다양한 언어들을 지원했습니다.
Dev Tools의 콘솔, Rest API 호출에 사용하는 queryDSL,
Kibana 내에서의 간단한 검색을 위한 KQL,
Pipeline, Runtime Field 등의 구성을 위한 Painless,
그 외에도 EQL, SQL, Canvas/Timelion 등
다양한 분야에 사용할 수 있도록 많은 언어를 지원합니다.
그럼에도 ES|QL이 등장한 것은,
이제 Elasticsearch의 쓰임새가 전문 검색을 넘어,
로그 탐색, 위협 헌팅, 리포팅, 알림, 사용자 지정 처리 등의 분야에 사용되기 때문입니다.
사용자들에게 외부 시스템으로 값비싼 전송을 할 필요가 없는
단일되고 통합된 방식으로 Elasticsearch에 접근할 수 있도록 한
보다 직관적인 언어가 바로 ES|QL입니다.
ES|QL의 특징
ES|QL은 파이프( | )를 사용해 단계별 방식으로 데이터를 조작하고 변환합니다.
한 작업의 출력 이후 다음 작업의 입력으로 이어지는 일련의 작업을 구성할 수 있어,
기존의 언어로는 어렵던 복잡한 데이터 변환과 분석이 가능합니다.
ES|QL은 단순한 언어 그 이상입니다.
ES|QL의 기능, 성능 요구사항을 달성하기 위해 Elasticsearch는 완전히 새로운 컴퓨팅 아키텍처를 구축했습니다.
ES|QL의 검색, 집계, 변환 기능은 기타 언어로 바뀌지 않고, 자체 내에서 직접 실행되기에 매우 뛰어난 성능으로 다양한 용도에 사용할 수 있습니다.
ES|QL 사용하기
Console (API)
Dev Tools의 콘솔에서 ES|QL을 사용할 수 있습니다.
ES|QL query의 기본 API 형식은 다음과 같습니다.
API의 """ ... """ 내에 ES|QL query를 입력 후 실행합니다.
POST /_query?format=txt
{
"query": """
"""
}
POST /_query?format=txt
{
"query": """
FROM sample_data
"""
}
Kibana Discover
Kibana의 Discover 메뉴 내에서 ES|QL을 사용할 수 있습니다.
Discover 메뉴 내의 Data View 선택 부분에서 Try ES|QL을 클릭합니다.
검색 대상 데이터에 timestamp가 포함되어 있는 경우, 우측 상단의 Time Filter를 확인 후 검색 범위에 맞게 조정합니다.
상단의 Query Bar에 ES|QL query를 입력해 검색을 진행할 수 있습니다.
더 쉽게 query를 작성할 수 있도록 각 명령어나 함수의 자동 완성 기능을 제공합니다.
Query 결과에 따라서 상단에 해당 결과에 맞는 시각화를 제공합니다.
시각화 패널 우측 상단의 Save, Edit 버튼을 통해 해당 시각화를 저장, 수정하여 Visualization 패널로 내보낼 수 있습니다.
ES|QL 기초 문법
Source Command
각 ES|QL 쿼리는 Source Command로 시작합니다.
Source Command는 일반적으로 Elasticsearch의 데이터를 바탕으로 한 테이블을 생성합니다.
Source Command에는 FROM 외에도 ROW, SHOW가 있으며,
자세한 설명은 링크에서 확인 가능합니다.
FROM kibana_sample_data_flights
Processing Command
Source Command 뒤에는 파이프 문자( | )로 구분된 Processing Command가 올 수 있습니다.
Processing Command는 행과 열을 추가, 제거, 수정하여 테이블을 변경합니다.
예시로, LIMIT 명령어를 통해 반환되는 행들의 수를 지정할 수 있습니다.
FROM kibana_sample_data_flights
| LIMIT 3
SORT 명령어를 통해 하나 이상의 열을 기반으로 행을 정렬할 수 있습니다.
FROM kibana_sample_data_flights
| SORT AvgTicketPrice DESC
WHERE 명령어를 통해 데이터 쿼리를 진행합니다.
FROM kibana_sample_data_flights
| WHERE AvgTicketPrice < 1000
WHERE과 함께 LIKE 연산자를 사용하면 Wildcard 쿼리가 가능합니다.
FROM kibana_sample_data_flights
| WHERE Dest LIKE "London*"
그 외에도
KEEP, DROP 등의 명령어로 테이블의 열을 유지, 삭제하거나
ENRICH 명령어로 elasticsearch의 인덱스 데이터를 테이블에 enrich 하거나,
DISSECT, GROK 명령어로 데이터를 가공할 수 있습니다.
자세한 Processing Command에 대한 설명은 이 링크에서 확인할 수 있습니다.
명령어 조합
파이프문자( | )로 구분하여 Processing Command를 연결할 수 있습니다.
각 Processing Command는 이전 라인의 출력 테이블에서 작동합니다.
ES|QL의 쿼리 결과는 마지막 Processing Command에 의해 생성된 테이블입니다.
열 추가
EVAL 명령어를 사용해 계산된 값을 테이블의 열로 추가할 수 있습니다.
항공권 평균 가격을 원화로 확인하기 위해 AvgTicketPriceKr 열을 생성
EVAL 명령어는 Function을 지원합니다.
Function에 대한 자세한 설명은 이 링크에서 확인할 수 있습니다.
비행 소요 시간을 소수점 아래 한 자리까지 시간 단위로 표현하기 위해
ROUND 함수를 사용
FROM kibana_sample_data_flights
| EVAL AvgTicketPriceKr = AvgTicketPrice * 1300
FROM kibana_sample_data_flights
| EVAL FlightTimeHourApprox = ROUND(FlightTimeMin / 60, 1)
집계
ES|QL을 사용해 집계를 수행할 수 있습니다.
STATS ... BY 명령어를 통해 통계를 계산합니다.
비행 거리 중간값 집계
STATS 명령어 한 줄에서 여러 번 집계할 수 있습니다.
비행 거리 중간값, 최대값 집계
BY를 사용해 선택한 열을 기준으로
집계를 Grouping 할 수 있습니다.
항공사별 비행 거리 중간값 집계
FROM kibana_sample_data_flights
| STATS median_distance_kilometers = MEDIAN(DistanceKilometers)
FROM kibana_sample_data_flights
| STATS median_distance_kilometers = MEDIAN(DistanceKilometers)
, max_distance_kilometers = MAX(DistanceKilometers)
FROM kibana_sample_data_flights
| STATS median_distance_kilometers = MEDIAN(DistanceKilometers) BY Carrier