+++
author = "kmplex"
title = "ELK Stack 개발부터 운영까지 4장"
date = "2022-03-03"
description = "Elastic Search 4장"
series = ["ES"]
categories = ["dev"]
+++
-
querycontext
- 질의에 대한 유사도를 계산해, 이를 기준으로 더 정확한 결과를 먼저 보여준다.
- 연관성에 따른 스코어 결과를 제공한다.
-
filter context
- 일치 여부에 따른 결과만 반환한다.
- 일치 여부만 제공한다.
- 스코어를 계산하지 않기때문에, 상대적으로 속도가 빠르다.
- 결과가 바뀌지 않기때문에 cache를 할 수 있다.
- cache 를 이용한 빠른 검색을 하기 위해선 filter context 를 사용해야한다.
-
위 context 를 구분하는 특별한 API 가 있는것은 아니며, 모두 search API 를 사용한다.
- filter 는 bool 내부의 filter type 에 적용된다.
- ES 에서 쿼리를 사용하는 방법은 query string / query DSL 두가지 방법이 있다.
- query String 은 한줄정도의 간단한 쿼리
- DSL 은 복잡한 쿼리에 사용된다. (json 기반 쿼리)
- URI 에 쿼리문을 작성하는 방식으로 사용된다.
GET kinbana_sample_data_ecommerce/_search?q=customer_full_name:Mary
- REST API 본문 안에 json 형태로 쿼리를 작성한다.
GET kinbana_sample_data_ecommerce/_search
{
"query" : {
"match" : {
"customer_full_name" : "Mary"
}
}
}
- query context 는 다양한 스코어 알고리즘을 사용한다.
- 기본은 BM25 알고리즘 (query 에 explain option 을 주면 볼 수 있음)
- ES 에서 query 는 크게 leaf query, compound query 로 나눌 수 있다.
- leaf 는 특정 필드에서 용어를 찾는 쿼리로, match / term / range query 가 있다. (전문 / 용어 수준 쿼리)
- compound query 는 조합해 사용하는 query 로, 대표적으로 bool query 가 있다.
-
전문 쿼리는 전문 검색을 하기 위해 사용되며, text type 으로 mapping 되어야한다.
-
용어 수준 쿼리는 정확히 일치하는 용어를 찾기 위해 사용되며, keyword type 으로 mapping 되어야한다.
- 강제는 아니지만, 권장사항이다.
-
전문쿼리의 과정은 아래와 같다.
-
- 입력 시, text type 이면 토큰들로 쪼개서 저장된다.
-
- 검색 시, 분석기를 통해 토큰으로 분리되고, 이를 매칭하여 검색한다.
-
-
전문 쿼리는 일반적으로 블로그 처럼 텍스트가 많은 필드에서 특정 용어를 검색하려 할때, 사용된다.
- 종류로는 match / match phrase query / query string query / multi-match query 등이 있다.
-
용어수준의 과정은 아래와 같다.
-
- keyword type 의 데이터를 인덱싱한다.
-
- 검색 시, 데이터가 일치하는지 검색한다.
-
-
용어수준은 인덱싱 과정 / 검색 과정에서 분석기를 거치지 않는다.
- term query, terms query , fuzzy query 등이 있다.
- 정확한 결과를 얻기 위해 사용한다.
- 대표적인 전문 쿼리로, 전체 텍스트 중에서 특정 용어를 검색할때 사용한다.
GET kinbana_sample_data_ecommerce/_search
{
# 특정 field 만 보여달라는 의미
"_source" : ["customer_full_name"],
"query" : {
"match" : {
"customer_full_name" : "Mary"
}
}
}
# Mary / bailey 로 토큰화 된다.
GET kinbana_sample_data_ecommerce/_search
{
# 특정 field 만 보여달라는 의미
"_source" : ["customer_full_name"],
"query" : {
"match" : {
"customer_full_name" : "Mary bailey"
}
}
}
# 토큰 조건에 and 를 걸 수 있다.
GET kinbana_sample_data_ecommerce/_search
{
# 특정 field 만 보여달라는 의미
"_source" : ["customer_full_name"],
"query" : {
"match" : {
"customer_full_name" : "Mary bailey",
"operator" : "and"
}
}
}
- 구는 2개 이상의 단어가 연결되어 만들어지는 단어이다.
- 용어 포함여부 뿐 아니라, 순서까지 맞아야한다.
- mary tony bailey 같은 케이스는 검색이 되지않는다.
# 많은 리소스를 소모하기에 자주 쓰는건 좋지 않다.
GET kinbana_sample_data_ecommerce/_search
{
"_source" : ["customer_full_name"],
"query" : {
"match_phrase" : {
"customer_full_name" : "Mary bailey"
}
}
}
- 용어 쿼리는 용어 수준 쿼리의 대표적인 쿼리이다.
- match 와 비슷하나, 분석기에 의해 토큰화 되지 않는다.
- 분석기를 거치지 않기에, 대소문자도 정확히 일치해야한다.
GET kinbana_sample_data_ecommerce/_search
{
"_source" : ["customer_full_name"],
"query" : {
"term" : {
# 대소문자가 일치하지 않아, 검색이 안된다.
"customer_full_name" : "Mary Bailey"
}
}
}
GET kinbana_sample_data_ecommerce/_search
{
"_source" : ["customer_full_name"],
"query" : {
"term" : {
# 저장은 분석기를 거쳐 되지만, 검색 시 분석기를 타지 않아, 대소문자 이슈로 검색 되지 않는다.
"customer_full_name" : "Mary"
}
}
}
GET kinbana_sample_data_ecommerce/_search
{
"_source" : ["customer_full_name"],
"query" : {
"term" : {
# 정확히 일치하는 경우에만 검색 된다.
"customer_full_name.keyword" : "Mary Bailey"
}
}
}
- 용어 수준 쿼리이며, 여러 용어들을 검색해준다.
- keyword type 에 매핑된 필드에만 사용되어야하며, 분석기를 타지 않는다.
GET kinbana_sample_data_ecommerce/_search
{
"_source" : ["day_of_week"],
"query" : {
"term" : {
"day_of_week" : ["Mondy","Sunday]
}
}
}
- 검색하고자 하는 용어 / 구절이 어떤 필드에 있는지 모르는 경우, 여러 개의 필드에 검색 요청을 보낼 수 있다.
- 전문 검색의 일종으로, text type 에 사용하는 것이 좋다.
GET kinbana_sample_data_ecommerce/_search
{
"_source" : ["customer_first_name", "customer_last_name", "customer_full_name"],
"query" : {
"muli_match" : {
"query" : "mary",
"fields" : [
"customer_first_name",
"customer_last_name",
"customer_full_name",
# "custmer*" wild card
# "customer_full_name^2" 가중치를 줄 수 도 있음
]
}
}
}
- 3개의 필드에서 개별 스코어를 구한다음, 가장 큰 값을 대표 스코어로 구한다.
- field 명이 많을땐, wild card 를 사용할 수 있다.
- 특정 날짜 및 숫자의 범위를 지정해 검색할때 사용된다.
- 날짜 / 숫자 / IP 데이터에 사용가능하다.
- 문자형 / keyword type 에 데이터에는 사용 할 수 없다.
GET kinbana_sample_data_ecommerce/_search
{
"query" : {
"range" : {
"timestamp" : {
# 쿼리에 사용한 날짜/ 시간 포맷과 실제 데이터의 포맷이 맞아야 정상 동작한다.
"gte" : "2020-12-15",
"lt" : "2020-12-16"
}
}
}
}
- gte 는 param <= x
- gt 는 param < x
- lte 는 x <= param
- lt 는 x < param
- 일주일 전 혹은 한달전 데이터를 검색하고 싶을땐, 아래처럼 범위 쿼리를 사용 할 수 있다.
GET kinbana_sample_data_ecommerce/_search
{
"query" : {
"range" : {
"timestamp" : {
# 쿼리에 사용한 날짜/ 시간 포맷과 실제 데이터의 포맷이 맞아야 정상 동작한다.
"gte" : "now-1M"
}
}
}
}
- ES Type 중 범위 데이터 타입이 있는데, 말 그대로 범위 데이터를 저장 할 수 있다.
GET kinbana_sample_data_ecommerce/_search
{
"query" : {
"range" : {
"test_date" : {
"gte" : "2021-01-21",
"lte" : "2021-01-29",
"relation":"within"
}
}
}
}
- intersects (default) : 쿼리 범위 값이 일부라도 포함되면 된다.
- contains 쿼리 범위 값을 모두 포함해야한다.
- within 쿼리 범위 값 내에 전부 속해야한다. (사용시 확인해볼 것)
- compound query 로 쿼리를 조합하여 사용 할 수 있다.
GET <index>/_search
{
"query": {
"bool" : {
# 참인 도큐먼트를 찾는다. []안에 복수개를 사용할 경우 AND 연산
"must": [
{ 쿼리문}
],
# 거짓인 도큐먼트를 찾는다.
"must_not":
{ 쿼리문}
,
# 참인 쿼리를 찾으며, []안에 복수개 쿼리를 사용할 경우 OR 연산
"should": [
{ 쿼리문}
],
# 예 / 아니오 형태의 필터 context 를 수행한다.
# 필터를 통해, 불필요한 스코어 계산을 줄일 수 있다.
"filter":
{ 쿼리문}
}
}
}
- 검색어를 정확히 모를 경우, 패턴을 이용해 검색 할 수 있다.
- 많은 리소스를 먹기에, 사용을 권장하진 않는다.
- 맨 앞에 사용 할 경우, 속도가 느려질 수 있다.
- 용어 수준의 쿼리에 해당 하므로, 분석기에 의해 분리된 용어를 찾기 위한 쿼리이다. => 근데 keyword type 에 쏘나 ..?
GET kinbana_sample_data_ecommerce/_search
{
"query" : {
# 정규식 쿼리도 사용 할 수 있다.
# "regexp" : {}
"wildcard" : {
"customer_full_name.keyword": "M?r*"
}
}
}