카테고리 없음

Elastic Search 가이드 북 - QueryDSL 정리

딤섬뮨 2025. 3. 30. 21:41
728x90

잇츠 스터디 4기에서 elastic search 스터디를 진행 하면서, elastic 가이드 북 중 QueryDSL 부분을 정리한 글입니다.

 

검색과 쿼리 - QueryDSL

Elastic Search 는 사용자가 여러가지 검색 조건을 통한 검색을 할 수 있도록 다양한 쿼리를 제공하고 있다.

이러한 쿼리를 QueryDSL 이라고 칭함.

모두 json 형식으로 입력해야 함.

 

풀 텍스트 쿼리?

실제로 검색에 사용되는 검색어인 Term 으로 분석 과정을 거쳐 저장하기 때문에 검색 시, 대소문자, 단수, 복수, 원형 여부에 관계 없이 검색이 가능함.

  • match_all
  • match
  • match_phrase
  • query_string

 

  1. match_all
    1. 만약 검색시 쿼리를 넣지 않으면 default 로 해당 쿼리를 이용해 검색해 줌.
    2. 해당 인덱스의 모든 도큐먼트를 검색함.
  2. match
    1. 특정 단어가 포함된 모든 문서를 검색한다.
    2. match 쿼리에 여러개의 검색어 작성시 ⇒ OR 조건 적용
    3. 만약 AND 조건을 적용하고 싶다면?operator 옵션 적용
      1. operator 옵션 적용
GET my_index/_search
{
  "query": {
    "match": {
      "message": "quick dog"
    }
  }
}
// quick 과 dog 중 어떤 하나라도 포함되면 검색

 

GET my_index/_search
{
  "query": {
    "match": {
      "message": {
        "query": "quick dog",
        "operator": "and" //적용
      }
    }
  }
}
// quick 과 dog 둘다 들어간 것만 검색

3. match_phrase

quick dog 이라는 구문을 공백 포함하여 정확히 검색 용

slop : 단어 사이에 다른 검색어가 끼어드는 것을 허용

GET my_index/_search
{
  "query": {
    "match_phrase": {
      "message": "lazy dog"
    }
  }
}

GET my_index/_search
{
  "query": {
    "match_phrase": {
      "message": {
        "query": "lazy dog",
        "slop": 1
      }
    }
  }
}

 

4. query string

  1. OR 이나 AND 같은 operator 기준으로 query string을 구분함.
  2. operator 기준으로 나뉘어 문장을 각자 독립적으로 분석함.
  3. 와일드 카드나, 복합 필드를 query 할 때 사용 가능.

 

Bool 복합 쿼리 - Bool Query

앞서 배운 여러 쿼리들을 조합하기 위해서 사용.

상위에 bool 이라고 명시하고, 그 안에 다른 쿼리들을 넣음.

  • must : 쿼리가 참인 도큐먼트들을 검색합니다.
  • must_not : 쿼리가 거짓인 도큐먼트들을 검색합니다.
  • should : 검색 결과 중 이 쿼리에 해당하는 도큐먼트의 점수를 높입니다.
  • filter : 쿼리가 참인 도큐먼트를 검색하지만 스코어를 계산하지 않습니다. must 보다 검색 속도가 빠르고 캐싱이 가능합니다.
GET <인덱스명>/_search
{
  "query": {
    "bool": {
      "must": [
        { <쿼리> }, …
      ],
      "must_not": [
        { <쿼리> }, …
      ],
      "should": [
        { <쿼리> }, …
      ],
      "filter": [
        { <쿼리> }, …
      ]
    }
  }
}
  • quick 과 일치하고, lazy dog 과 일치하지 않는 모든 결과 값을 조회한다
GET my_index/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "match": {
            "message": "quick"
          }
        },
        {
          "match_phrase": {
            "message": "lazy dog"
          }
        }
      ]
    }
  }
}

must 랑 should 를 섞어쓰면 주의해야 함.

 

문제

{
    "query": {
        "bool": {
            "should": [
                {
                    "match": {
                        "name": "Messi"
                    }
                }
            ],
            "filter": [
                {
                    "match": {
                        "sports": "basketball"
                    }
                }
            ]
        }
    }
}

 

기대했던 것

  • name 이 Messi 인 결과 중에 sports 가 basketball인 값을 가져온다.

결과

  • 하지만 should 조건은 무시되고 sports에 basketball만 있는 애들을 가져옴.

  • must 나 filter 쿼리가 없다면 minimum_should_match는 디폴트 값이 0
    • 하나라도 일치 안해도 상관 없다는 뜻이니깐, must 조건만 참이여도 반환하게 됨.
  • minimun_should_match 가 1이라도 돼야, 일치하는게 1개라도 있으면 참을 반환하게 됨

해결방안

  • minimum_should_match 값을 1로 변경
  • should match대신 must 를 사용

 

 

정확도(Relevancy)?

RDBMS 는 쿼리 조건에 부합하는 것만 결과를 가져오는 것.

각 결과들이 얼마나 정확한지에 대한 판단은 불가능.

Elastic search 는 얼마나 비슷한지 판단하는 알고리즘이 있음.

이 정확도를 기반으로 사용자가 원하는 데이터 조회 가능.

 

  • score
    • 검색 조건과 얼마나 일치하는지
    • 점수가 높은 순으로 결과를 보여줌.
    • 각 결과에서 _score 부분에 표시됨.

max_score 에서는 전체 결과 중 가장 높은 점수가 표시됨.

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 5,
      "relation" : "eq"
    },
    "max_score" : 0.8762741,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.8762741,
        "_source" : {
          "message" : "The quick brown fox jumps over the quick dog"
        }
      },
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.6744513,
        "_source" : {
          "message" : "The quick brown fox jumps over the lazy dog"
        }
      },
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.6173784,
        "_source" : {
          "message" : "The quick brown fox"
        }
      }
      }
    ]
  }
}

 

score 을 매기는데 사용되는 알고리즘 = BM25 알고리즘

 

BM25 알고리즘?

  • BM : Best Matching 알고리즘

 

 

TF (Term Frequency)

  • 쥬라기 공원이 5번 들어있는 페이지보다 10번 든 페이지가 더 확률이 높다.
  • 다다익선
  • 25개 이후로는 비슷한 점수 부여

IDF (Inverse Document Frequency)

  • 자신을 포함한 도큐먼트 개수가 많을수록 그 텀의 자신의 점수가 감소하는 것.
  • 전체에서 쥬라기는 10번, 공원은 100번있는 단어라면 쥬라기가 더 중요한 term
  • IDF 가 작다 == 점수가 낮다.

Field Length

  • 텍스트 길이가 더 짧을수록 더 점수가 높음.

 

Bool : Should

검색 점수를 조정하기 위해 사용할 수 있음.

이 결과들 중 lazy 가 포함된 결과에 가중치를 줘서 상위로 올리고 싶으면

다음과 같이 should 안에 lazy 를 찾는 검색을 추가합니다.

 

GET my_index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "message": "fox"
          }
        }
      ],
      "should": [
        {
          "match": {
            "message": "lazy"
          }
        }
      ]
    }
  }
}

 

정확값 쿼리(Exact Value Query)

풀 텍스트 검색은 스코어 점수 기반으로 정확도 기반으로 높은 결과부터 조회됨.

하지만, 참 / 거짓만 판단하여 결과를 조회할 수 있기도 함.

  • bool : filterEx. 쇼핑몰에서 검색어로 정확도가 높은 상품명을 검색하면서, 생산 업체를 다시 필터링하는 용도
    • 하위 쿼리를 사용하면 스코어에 영향을 주지 않는다.
  • keyword스코어는 계산하지 않고, 정확도만 따지기 때문에 스코어가 0.0 , filter 안에 넣고 사용할 것
    • 공백, 대소문자까지 완전히 일치하는 데이터를 리턴함.

범위 쿼리(Range Query)

문자열 필드 외에 숫자나, 날짜 형식들의 저장이 가능함.

정확도를 계산하지 않는다.

가깝거나 멀다고 정확도가 변하진 않음.

하지만 가깝거나 멂 정도에 따라 정확도를 부여하고 싶다면 function_score 적용 가능

 

Elastic Search 성능 튜닝

  1. Bulk 요청 사용
    1. 한번에 여러 문서를 인덱싱할 수 있게해줌.
    • 단일 문서 인덱싱보다 개선됨
    • 적절한 벌크 요청을 위해서는 밴치마크 테스트 수행
      • 속도가 정체되는 시점을 찾기.
    • 너무 큰 bulk는 메모리 압박을 초래함
  2. 여러 작업자 / 스레드 사용.
    1. 단일 스레드로 bulk 요청을 보내는 것은 전체 리소스를 활용하기 어려움.
    2. 여러 스레드나 프로세스를 이용하면 데이터 전송 속도를 높임
    3. I /O 나 CPU 가 포화 상태에 이를 때 최적의 스레드 수를 찾기.
  3. refresh 간격 설정?
    1. 색인된 문서를 검색 가능하게 만드는 작업
    2. 색인될 때 메모리 버퍼에 저장되고, refresh가 발생할 때 이 메모리 버퍼에 있는 문서들이 새로운 "검색 가능한" 세그먼트로 변환
    3. 원래는 1초마다 반복하지만, 이걸 조절하면 좋음 ex. 30초
    4. 초기 데이터 로드 시, refresh 와 replica 비활성화
  4. 메모리,디스크 관련
    1. I/O 작업을 버퍼링하는데 파일 시스템 캐시를 사용하므로 전체 메모리의 절반을 이 캐시용으로 할당
    2. 더 빠른 SSD 를 사용하거나 로컬 디스크를 사용
    3. 버퍼 크기를 512MB 정도 각 샤드에 할당하면 성능이 개선
    4. jvm 메모리의 10퍼센트가 주로 할당됨.
  5. 느린 쿼리
    1. slow log를 켜서 실행 속도가 느린 쿼리를 식별 가능.
728x90