Skip to content

Latest commit

 

History

History
358 lines (292 loc) · 10.1 KB

04.md

File metadata and controls

358 lines (292 loc) · 10.1 KB
+++
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 에 적용된다.

Query String / DSL

  • ES 에서 쿼리를 사용하는 방법은 query string / query DSL 두가지 방법이 있다.
    • query String 은 한줄정도의 간단한 쿼리
    • DSL 은 복잡한 쿼리에 사용된다. (json 기반 쿼리)

query string

  • URI 에 쿼리문을 작성하는 방식으로 사용된다.
GET kinbana_sample_data_ecommerce/_search?q=customer_full_name:Mary

query DSL

  • REST API 본문 안에 json 형태로 쿼리를 작성한다.

GET kinbana_sample_data_ecommerce/_search
{
    "query" : {
        "match" : {
            "customer_full_name" : "Mary"
        }
    } 
}

유사도 스코어

  • query context 는 다양한 스코어 알고리즘을 사용한다.
  • 기본은 BM25 알고리즘 (query 에 explain option 을 주면 볼 수 있음)

Query

  • ES 에서 query 는 크게 leaf query, compound query 로 나눌 수 있다.
    • leaf 는 특정 필드에서 용어를 찾는 쿼리로, match / term / range query 가 있다. (전문 / 용어 수준 쿼리)
    • compound query 는 조합해 사용하는 query 로, 대표적으로 bool query 가 있다.

전문 쿼리와 용어 쿼리

  • 전문 쿼리는 전문 검색을 하기 위해 사용되며, text type 으로 mapping 되어야한다.

  • 용어 수준 쿼리는 정확히 일치하는 용어를 찾기 위해 사용되며, keyword type 으로 mapping 되어야한다.

    • 강제는 아니지만, 권장사항이다.
  • 전문쿼리의 과정은 아래와 같다.

      1. 입력 시, text type 이면 토큰들로 쪼개서 저장된다.
      1. 검색 시, 분석기를 통해 토큰으로 분리되고, 이를 매칭하여 검색한다.
  • 전문 쿼리는 일반적으로 블로그 처럼 텍스트가 많은 필드에서 특정 용어를 검색하려 할때, 사용된다.

    • 종류로는 match / match phrase query / query string query / multi-match query 등이 있다.
  • 용어수준의 과정은 아래와 같다.

      1. keyword type 의 데이터를 인덱싱한다.
      1. 검색 시, 데이터가 일치하는지 검색한다.
  • 용어수준은 인덱싱 과정 / 검색 과정에서 분석기를 거치지 않는다.

    • term query, terms query , fuzzy query 등이 있다.
    • 정확한 결과를 얻기 위해 사용한다.

match 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"
        }
    } 
}

match phrase query

  • 구는 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]
        }
    } 
}

multi match query

  • 검색하고자 하는 용어 / 구절이 어떤 필드에 있는지 모르는 경우, 여러 개의 필드에 검색 요청을 보낼 수 있다.
    • 전문 검색의 일종으로, 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*"
        }
    } 
}