Elastic Search

Ch04. 데이터 검색 - Query DSL 이해하기

webmaster 2025. 9. 14. 18:01
728x90

QueryDSL 쿼리 구조

요청 구조

{
    "size" :,
    "from" : ,
    "timeout" : ,
    " _source":{ },
    "query" : { },
    "aggs" : { },
    "sort" : { }
}
  • Size: 리턴 받는 결과의 개수를 지정한다(기본값은 10)
  • From: 몇 번째 문서부터 가져올지를 지정한다(기본값은 0이다)
  • timeout: 검색을 요청해서 결과를 받는 데까지 걸리는 시간을 설정한다(기본값은 무한대)
    • timeout을 너무 짧게 잡으면 전체 샤드에서 timeout을 넘기지 않은 문서만 결과로 출력된다.
  • _source: 검색 시 필요한 필드만 출력하고 싶을 때 사용한다.
  • query: 검색 조건문이 들어가야 하는 공간
  • aggs: 통계 및 집계 데이터를 사용할 때 사용하는 공간
  • sort: 문서 결과를 어떻게 출력할지에 대한 조건을 사용하는 공간

응답 구조

{
	"took":
	"timed_out":
	"_shards": {
		"total":
		"successful":
		"failed":
    },
	"hits": {
		"total":
		"max_score" :
		"hits": [ ]
	}
}
  • took: 쿼리를 실행한 시간을 나타낸다.
  • timeout: 쿼리 시간이 초과할 경우를 나타낸다.
  • shards.total: 쿼리를 요청한 전체 샤드의 개수를 나타낸다.
  • shards.successful: 검색 요청에 성공적으로 응답한 샤드의 개수를 나타낸다.
  • shards.failed: 검색 요청에 실패한 샤드의 개수를 나타낸다.
  • hits.total: 검색어에 매칭된 문서의 전체 갯수를 나타낸다.
  • hits.max_score: 일치하는 문서의 스코어 값 중 가장 높은 값을 출력한다.
  • hits.hits: 각 문서 정보와 스코어 값을 보여준다.

QueryDSL 쿼리와 필터

실제 분석기에 의한 전문 분석이 필요한 경우에는 쿼리 컨텍스트를 사용하고, 단순 Yes/No로 판단할 수 있는 조건 검색은 필터 컨텍스트를 사용한다.

  쿼리 컨텍스트 필터 컨텍스트
용도 전문 검색 시 사용 조건 검색 시, 사용(Yes/No)
특징 분석기에 의해 분석됨
연관성 관련 Score를 계산
루씬 레벨에서 분석 과정을 거쳐야 하므로 상대적 느림
Yes/No로 단순 판별 가능
연관성 관련 계산을 하지 않음
엘라스틱서치 레벨에서 처리가 가능하므로 상대적 빠름
사용 예 "Harry Pottor" 같은 문장 분석 "create_year" 필드의 값이 2018년도 인지 여부
"status" 필드에 "Use"라는 코드 포함 여부
  • 어떤 질의 방식을 사용하는지에 따라 엘라스틱 서치 내부의 검색 과정이나 성능이 크게 달라지기 때문에 가능한 용도에 맞게 사용해야 한다.

쿼리 컨텍스트

POST movie_search/_search
{
  "query": {
    "match": {
      "movieNm": "기묘한 가족"
    }
  }
}
  • 문서가 쿼리와 얼마나 유사한지를 스코어로 계산한다.
  • 질의가 요청될 때마다 엘라스틱서치에서 내부의 루씬을 이용해 계산을 수행한다(결과 캐싱 X)
  • 일반적으로 전문 검색에 많이 사용한다.
  • 캐싱되지 않고 디스크 연산을 수행하기 때문에 상대적으로 느리다.

필터 컨텍스트

POST movie_search/_search
{
  "query": {
    "bool": {
      "must": [
        { "match_all": {} }
      ],
      "filter": [
        { "term": { "repGenreNm": "다큐멘터리" } }
      ]
    }
  }
}
  • 쿼리의 조건과 문서가 일치하는지를 구분한다.
  • 별도로 스코어를 계산하지 않고 단순 매칭 여부를 검사한다.
  • 자주 사용되는 필터의 결과는 엘라스틱서치가 내부적으로 캐싱한다.
  • 기본적으로 메모리 연산을 수행하기 때문에 상대적으로 빠르다.

QueryDSL 주요 파라미터

Multi Index rjator

POST movie_search,movie_auto/_search
{
  "query": {
    "term": {
      "repGenreNm": "다큐멘터리"
    }
  }
}
  • 다수의 인덱스를 검색해야 할 때도, 한 번의 요청으로 검색 결과를 얻을 수 있다.
  • movie_search, movie_auto 인덱스를 모두 검색한다.
  • Multi Index 쿼리를 이용하면 다수의 비정형 데이터를 가지고 있는 경우에도 한 번에 검색할 수 있다.
  • 인덱스 이름을 지정할 때 * (와일드카드)를 사용할 수 있다.

쿼리 결과 페이징

//첫번째 페이징 요청
POST movie_search/_search
{
  "from": 0,
  "size": 5,
  "query": {
    "term": {
      "repNationNm": "한국"
    }
  }
}
//두번째 페이징 요청
POST movie_search/_search
{
  "from": 5,
  "size": 5,
  "query": {
    "term": {
      "repNationNm": "한국"
    }
  }
}
  • 제공되는 문서의 시작을 나타내는 from 파라미터와 문서의 개수를 나타내기 위한 size 파라미터를 사용해야 한다.
  • 엘라스틱 서치는 RDMS와 다르게 페이징 된 데이터만 읽는 것이 아니라 모든 데이터를 읽게 된다.
    • 설정된 페이지를 제공하기 위해서는 전체를 읽어서 사이즈만큼 필터링해서 제공하는 구조이다.
    • 페이지 번호가 높아질수록 쿼리 비용은 높아진다.

쿼리 결과 정렬

POST movie_search/_search
{
  "query": {
    "term": {
      "repNationNm": "한국"
    }
  },
  "sort": [
    {
      "prdtYear": {
        "order": "asc"
      }
    }
  ]
}
  • 엘라스틱서치가 계산한 유사도에 의한 스코어 값으로 정렬하는 것이 아닌 필드의 이름이나, 가격, 날짜 등을 기준으로 정렬하고 싶은 경우 사용한다.
  • 정렬을 위한 옵션으로 asd(오름차순), desc(내림차순)을 제공한다.
  • _score 값을 통해 정렬 순위를 결정할 수도 있다.

_source 필드 필터링

POST movie_search/_search
{
  "_source": [
    "movieNm"
  ],
  "query": {
    "term": {
      "repNationNm": "한국"
    }
  }
}
  • _source 항목 아래에 실제 데이터가 존재하며 문서 내부에 존재하는 각 필드가 결과로 제공된다.
  • 특정 컬럼만 출력하고 싶을 경우 _source에 검색결과에 포함하고 싶은 필드를 지정하면 된다.

범위 검색

POST movie_search/_search
{
  "query": {
    "range": {
      "prdtYear": {
        "gte": "2016",
        "lte": "2017"
      }
    }
  }
}
  • 숫자나 날짜 데이터의 경우 지정한 값이 아닌 범위를 기준으로 질의할 때가 있는데 이때 사용한다.
  • lt(<) : 피연산자보다 작음
  • gt(>): 피연산자보다 큼
  • lte(<=): 피연산자보다 작거나 같다
  • gte(>=): 피연산자보다 크거나 같다

operator 설정

POST movie_search/_search
{
  "query": {
    "match": {
      "movieNm": {
        "query": "자전차왕 엄복동",
        "operator": "and"
      }
    }
  }
}
  • 엘라스틱 서치는 검색 시 문장이 들어올 경우 기본적으로 or 연산으로 동작하는데, Operator 파라미터를 통해 "and", "or" 연산자를 명시적으로 지정할 수 있다.
  • operator 파라미터가 생략된 경우 기본적으로 term과 term에 or 연산이 적용된다.

minimum_should_match 설정

POST movie_search/_search
{
  "query": {
    "match": {
      "movieNm": {
        "query": "자전차왕 엄복동",
        "minimum_should_match": 2
      }
    }
  }
}
  • Term에 몇 개 이상 매칭될 때만 검색 결과로 나오게 하기 위해서는 minimum_should_match를 사용하면 된다.
  • minimum_should_match 파라미터를 써서 and와 비슷한 효과를 낼 수 있다.

fuzziness 설정

POST movie_search/_search
{
  "query": {
    "match": {
      "movieNmEn": {
        "query": "Fli High",
        "fuzziness": "AUTO"
      }
    }
  }
}
  • 단순히 같은 값을 찾는 Match Query를 유사한 값을 찾는 FuzzyQuery로 변경할 수 있다.
    • 레벤슈타인 편집 거리 알고리즘을 기반으로 문서의 필드 값을 여러 번 변경하는 방식으로 동작한다.
    • 유사한 검색 결과를 찾기 위해 허용 범위의 Term으로 변경해 가며 문서를 찾아 결과로 출력한다.
  • 오차범위 값으로 0, 1, 2, auto 값을 설정할 수 있으며, 한국어에는 적용하기 어렵다.(영어는 사용 가능)

boost 설정

POST movie_search/_search
{
  "query": {
    "multi_match": {
      "query": "Fly",
      "fields": ["movieNm^3", "movieNmEn"]
    }
  }
}
  • Boost 관련 설정은 검색에서 가장 많이 사용하며, 관련성이 높은 필드나 키워드에 가중치를 더 줄 수 있게 해 준다.
  • ^은 부스트 연산자로 중요도를 높게 설정해 줄 수 있다.
728x90