본문 바로가기

언어/Java

ElasticSearch 스터디 정리 (4) - Query DSL 1

개요

엘라스틱서치는 검색엔진이니 만큼 검색은 매우 중요한 부분이라고 볼수 있다. 그래서 Query DSL이라는 특수한 쿼리 문법을 제공함으로써 다양한 검색 기능을 활용 할 수 있다. HTTP + JSON 검색으로 간편성은 제공하지만 JDBC 처럼 TCP/IP 기반 클라이언트를 제공함으로써 더 빠른 검색이 가능하게 하면 좋지 않았을까 라는 생각이 든다.

검색 API

색인시점에서는 앞에 공부한 내용처럼 분석기(standard)로 구분되어 색인될것이다.

trying out Elasticsearch => trying, out, elasticsearch
Hello Elasticsearch => hello, elasticsearch
Term Document
trying 1
out 1
elasticsearch 1, 2
hello 2

그리고 검색을 아래와 같이 검색 한다면 1번 Document를 결과로 얻을수 있습니다. (자세한 검색 내용은 아래 Query DSL 에서 설명하겠습니다.)

{
  "query": {
    "match": {
      "text": "TRY OUT"
    }
  }
}

검색 방식

  • URI
    • HTTP GET 활용
    • 파라미터를 KEY=VALUE 쿼리 방식으로 전달
    • 간단한 검색에서 활용
      • RFC 2616 / RFC 3986 에서 얘기한것 처럼 파라미터 쿼리의 최대 크기는 없다. 하지만 DNS는 255 길이를 초과 할수 없다. (이건 문제 되기 힘듬)
      • 다만 웹브라우저 이용시 크롬 기준 64k 이상 길이를 가지는 경우 표시하지 않으며 100k 까지는 이상 없이 입력 할 수 있다.
    • 파라미터
      • q
        • optional, string
        • 검색 수행 쿼리 조건
      • df
        • optional, string
        • q에서 필드 미지정시 기본값으로 검색할 필드 지정
      • analyzer
        • optional, string
        • q 쿼리 분석할때 사용할 분석기 지정
      • analyze_wildcard
        • optional, boolean
        • 와일드카드(*) 검색 활성화 여부 (2019-* 이런 방식으로 2019로 시작되는 부분을 검색 할 수 있음)
      • default_operator
        • optional, string
        • 검색 조건 연산자(AND, OR)
      • _source
        • optional, string (true, false 인데 왜 string?)
        • 검색 결과에 본문 포함 여부
      • sort
        • optional, string
        • 검색 결과 정렬 필드 지정
      • from
        • optional, integer
        • 문서 시작 위치 설정(페이징)
      • size
        • optional, integer
        • 검색 결과 개수(페이징)
      • 기타
        • allow_partial_search_results
        • batched_reduce_size
        • explain
          • hit 별로 score 계산방식 설명
        • lenient
        • search_type
        • _source_excludes
          • _source 에서 제외할 필드
        • _source_includes
          • _source 에서 포함될 필드
        • track_scores
        • track_total_hits
        • timeout
        • terminate_after
  • RequestBody
    • RESTful API 활용
    • BODY에 JSON 형태로 Query DSL 표현
    • 복잡한 검색에서 활용

Query DSL

기본 쿼리 구조

Request 구조

{
  "size": "...",            // 결과 개수 지정
  "from": "...",            // 페이징 처리를 위한 몇번째 문서 지정
  "timeout": "...",            // timeout 지정. timeout 이되면 에러를 반환 하는게 아니라 timeout 까지 조회된 결과 반환
  "_source": "...",            // 검색시 필드한 필드만 추가
  "query": "...",            // 검색 조건문
  "aggs": "...",            // 통계 및 집계 데이터
  "sort": "...",            // 정렬 조건
}

Response 구조

{
  "took": "...",                // 수행 시간

  "timed_out": "...",            // timeout 시

  "_shards": {
    "total": "...",                // 전체 샤드 개수
    "successful": "...",        // 응답 성공 샤드 개수
    "failed": "...",            // 응답 실패 샤드 개수
  },

  "hits": {
    "total": "...",                // 전체 결과 갯수
    "max_score": "...",            // 일치 결과 스코어중 가장 높은 값
    "hits": [{}, {}]            // 결과 및 해당 결과의 스코어
  }
}

쿼리와 필터

  쿼리 컨텍스트 필터 컨텍스트
용도 전문 검색 시 사용 조건 검색시 사용
특징 - 분석기에 의해 분석이 수행됨
- 연관성 score 계산
- 루씬 레벨 분석이 이루어짐으로 상대적 느림
- 결과가 캐싱되지 않음
- 디스크 연산으로 상대적 느림
- Yes/No로 단순 판별
- 연관성 score 계산하지 않음
- 메모리 연산 수행으로 상대적 빠름
- 결과를 내부적으로 캐싱함
"Harry Potter" 같은 text 타입 문장 분석 - create_year 이 2019 인지 체크
- status 가 use 인지 체크

검색 옵션

  • multi index 검색
    • , 로 구분해서 검색시 여러개 index에서 결과를 가져 올수 있다.
    • index명에 와일드카드 지정 가능. 로그 데이터가 날짜별 index로 생성되는 경우(yyyy-MM-dd 같은 케이스)에서 2019-* 로 조회해서 2019년에 생성된 index 로그에서 어떤 값들을 조회 할 수 있다.
  • 결과 페이징
    • from, size 를 이용해서 페이징을 구현 할 수 있다.
    • 다만 RDBMS 와 다르게 페이징된 값만 읽어오는게 아니라 전체를 읽어와서 필터링해서 응답을 주기 때문에 from 이 커지면 쿼리 비용이 높아진다.
      • from = 0, size = 5 인 경우 5개만 조회하고 5개를 응답한다.
      • from = 10, size = 5 인 경우 15개를 조회하고 5개를 응답한다.
  • 결과 정렬
    • sort를 이용해서 정렬
    • 설정하지 않으면 score 값으로 정렬
    • asc 또는 desc 를 통해서 오름차순 내림차순 정렬 가능
  • _source 필드 필터링
  • 범위 검색
    • 날짜 또는 숫자 데이터 경우 범위 기준 질의에서 사용
    • 문법
      • lt (<)
      • gt (>)
      • lte (<=)
      • gte (>=)
  • operator 설정
  • minimum_should_match
    • OR 연산 수행시 최소 몇개 이상 매칭 되도록 설정
  • fuzziness 설정
    • 유사한 검색 결과 찾기 위함
    • 0, 1, 2, AUTO로 설정 할 수 있다.
      • AUTO
        • AUTO:[low],[high] 방식으로 설정한다.
        • low는 기본3, high 기본 6이다. (term 개수)
        • low, high 값으로 3개 구간으로 나눠진다.
          • 0 ~ 2(low - 1): fuzziness 0 적용
          • 3 ~ 5(hign - 1): fuzziness 1 적용
          • 6(high) ~ : fuzziness 2 적용
  • boost 설정
    • 관련성이 높은 필드나 키워드에 가중치를 더 주게 하기 위함으로 검색 정확성 높일수 있음.

Query DSL 주요 쿼리

match all

색인에 모든 문서를 검색하는 쿼리. 일반적으로 색인에 저장된 문서 확인용으로 사용함.

## POST movie_search/_search
{
  "query": {
    "match_all": {}
  }
}

match

텍스트, 날짜, 숫자 등 포함된 문장을 형태소 분석을 통해 term으로 분리후 검색 수행. 기본적으로 검색어가 분석되어야 하는 경우 사용.

## POST movie_search/_search
{
  "query": {
    "match": {
      "movieNm": "그대 장미"
    }
  }
}

multi match

match와 사용법은 비슷하나 여러개 필드에서 검색 할때 사용

## POST movie_search/_search
{
  "query": {
    "multi_match": {
      "query": "가족",
      "fields": ["movieNm", "movieNmEn"]
    }
  }
}

term

분석기를 통하지 않고 텍스트 형태 데이터를 조회 할때 사용한다. text 타입 경우 인지 하고 사용하자. (분석기를 통하지 않기 때문에 대소문자는 물론 완벽히 같은 값이 아닐 경우 조회 되지 않을 수 있다.) 주로 keyword 타입 검색시 사용.

## POST movie_search/_search
{
  "query": {
    "term": {
      "movieNm": "그대 장미"
    }
  }
}

bool

RDBMS 처럼 여러개 조건을 AND 또는 OR로 조합해서 사용할때.

## POST movie_search/_search
{
  "query": {
    "bool": {
      "must": [],
      "must_not": [],
      "should": [],
      "filter": []
    }
  }
}
ES RDBMS 설명
must AND 칼럼 = 조건 반드시 만족해야 함
must_not AND 칼럼 != 조건 반드시 만족하지 않아야 함
should OR 칼럼 = 조건 하나 이상 만족해야 함
filter IN (조건) 조건에 포함된 결과. score 정렬 되지 않음