ElasticSearch 풀 텍스트 쿼리 - QueryString

Munang·2021년 7월 13일
0

url 뒤에 붙여 사용자의 입력데이터를 서버로 전송하는 방법 중 하나이다.
query parameters( 물음표 뒤에 = 로 연결된 key value pair 부분)을 url 뒤에 덧붙여서 추가적인 정보를 서버 측에 전달하는 것이다.
웹개발을 해본 사람이라면 무슨 의미인지 바로 알 것 같다.

예를들어, 지금 내가 사용하는 포스트 작성하는 페이지의 url을 확인하면 다음과 같은 형식이다.

https://velog.io/write?id=ffff

write 하는 부분으로 POST api를 날리고, 파라미터를 id로 받는다. 여기서 id값은 ffff값이 될 것이다.

대충 생각하면 이럴 것 같음 (갑분 스프링 부트..ㅋㅋㅋ)

@Controller 

public class TestController {
	@RequestMapping("https://velog.io/write")
    	public String writePost(@RequestParam("id"), Model model) {
    		model.addAttribute("id", id); 
            	+id기반 데이터 베이스 업데이트 해주는 비즈니스 로직
            return "https://velog.io/board"; 
       } 
}

이미 저장된 게시글이면 데이터베이스에 게시글 관련 내용이 없데이트 될 것이고, 저장되지 않은 게시글이면
자동으로 새로 생성한 후 저장하기를 누를때 게시글 내용이 데이터 베이스에 업데이트 될 것이다.

아무튼.. 뭐 결론적으로

쿼리스트링은 파라미터, 값을 url방식으로 넘겨주는 약속된 형태의 문자열이라는 것이다.

근데 이 문자열이 엘라스틱 서치에도 사용된다는 것이다!
엘라스틱 서치는 RESTful API를 제공하기 때문이다. 동일하게 사용가능하다.

하지만 여기서 놀라운 점은 API주소뿐 아니라 queryDSL에도 사용이
가능하다는 것이다!!!
나는 현업에서 은근 많이 사용했기 때문에, 그리고 정규표현식을 사용하기 때문에 동시에 개념정리를 해둬야겠다. 그때 많이 애를 먹었던 기억이 있다. ㅎㅎ
앞으로 queryDSL에서의 querystring을 알아볼 것이다.


1. ElasticSearch

나는 공식 문서에 나와있는 내용들을 번역하고 쉽게 정리하는 위주로 게시글을 작성할 것이다.
대충 내용을 알고 쿼리를 날려도.. 내가 원하던 결과가 나오지 않았던 경우가 정말 많았다. 그것은 대충 알았기 때문 ^^.. 아무튼 정확히 알기 위해 포스팅을 작성한다.

(1). 개념

공식 문서에서는 쿼리 스트링은 query string syntax를 사용한다고 나와있다. 목적은 AND나 OR과 같은 연산을 하기 위해서이다.

  • 쿼리를 날리는 인덱스에 텍스트 필드가 포함되어 있다면, 분석 과정을 거치게 된다. 즉 원하는 형태의 텍스트가 포함된 도큐먼트만 추출하기 위해 분석과정을 진행한다. (참고:ES공식 사이트에서는 다음과 같은 경우가 있다면 반드시 분석 과정이 필요하다고 말한다.)
Build a search engine
Mine unstructured data
Fine-tune search for a specific language
Perform lexicographic or linguistic research
  • 분석 이후, 매칭되는 도큐먼트를 리턴하기 이전에 쿼리 스트링을 수행한다.
  • 즉 다시말하면, 쿼리스트링은 텍스트 분석 후에 사용되는 과정으로 도큐먼트 필드에 텍스트타입이 없다면 쓸 일이 없을 것이다.
  • 공식 문서에는 가급적 simple query string 이나 match를 사용하기를 권장하고 있다.
  • 왜냐면 쿼리스트링의 문법이 엄격한 편이기 때문에 맞추기가 까다롭다. 대부분 정규표현식과 같이 쓰게 되는데, 이렇게 복잡한 경우가 아닌 이상 simple query string, match와 같은 텍스트 쿼리를 쓰라고 권장하고 있다.

(2). 예시

다음과 같은 search 쿼리문이 수행된다고 생각해보자.
쿼리 스트링 속성에서 쿼리 부분을 new york city 와 big apple 으로 2분할 한다.
여기서 주목해야 할 점은 원래 match 쿼리를 사용하게 되면, new, york, city가 각각 토큰으로 분리되어 or연산을 수행하게 되고 하나의 단어라도 맞으면 스코어 점수가 생겨 hits에 포함된다.
하지만, 쿼리 스트링에서는 new york city 3가지 항목이 통째로 토큰으로 취급된다. 왜냐면 쿼리스트링 문법에서 whitespace자체가 어떤 연산으로 취급되지 않기 때문이다.
쿼리 스트링 속성 안에서는 모두 쿼리스트링 문법이 적용된다.

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": 
    "query_string": {
      "query": "(new york city) OR (big apple)",
      "default_field": "content"
    }
  }
}
'

(3). 쿼리스트링 파라미터 query string parameter

쿼리 스트링속성을 사용하게 되면, 파라미터로 다음과 같은 인자들을 사용할 수 있다.

  • query : 앞선 (1)개념에서 언급했던 쿼리스트링 신택스이다. (2)에서 보면 (new york city) OR (big apple) 부분이 쿼리 신택스라고 생각하면 된다.
    실제 사용할 때에는 "query" : "쿼리스트링 신택스" 형태로 사용한다.
  • default_field : (2)의 예시에서 본 것 처럼, 해당 쿼리를 검색할 필드를 정해준다. 정해주지 않을 경우 모든 필드에서 매칭되는지의 여부를 검색한다. 여기서 주의할 점은 nested쿼리의 형태로 지원하지 않는다.
왜냐면 !!(예를 들어서, default_field 가 무냉이고, 
query는 화이팅 이라고 검색했다면 
무냉 필드에서 화이팅이라는 내용을 가진 
도큐먼트n개를 하나로 묶어서 리턴해주는 key:value 형태는 지원하지 않는다는 의미) 
비용이 많이 든다는 점이다. 
쿼리 필드의 불쿼리(쿼리스트링이 아니라 쿼리 필드!!)를 사용하게 되면, 
기본적으로 리턴되는 도큐먼트 개수는 1024개 이다. (메모리 제한때문에)
  • allow_leading_wildcard: 이 속성을 true로 설정하게 되면, * 이나 ? 을 쿼리스트링.쿼리의 첫 문자로 넣는 것을 가능하게 한다.
    -> 나는 처음에 이 속성이 이해가 안갔다. 첫 문자로 넣는걸 가능하게 한다고? .. 무슨 소리지..? 넣으면 넣고 아니면 마는거 아닌가? 싶었다. es 깃헙 이슈를 보니 이런 게시글이 있었다.
    7.9.0에서는 이 속성이 잘 돌아갔는데, 7.9.1에서는 false로 했는데도 오류가 안나오고 도큐먼트가 리턴됐다는 내용이다.
    -> 해당 글로 유추해보면 이 속성은 와일드 카드나 ?를 쿼리문의 첫 글자에 사용할 수 있게 해주는 속성같다. false로 두면, 첫글자로 와일드카드나 ?는 사용할 수 없는 것이다.
    -> 근데 왜 이런 속성을 넣었을까? 와일드 카드를 첫글자에 쓰냐 안쓰냐가 어떤 중요한 문제가 되는것인가? 도저히 감이 안온다.
    !! 관련된 예시를 찾게 되면 포스팅을 수정하겠다 ! 이부분은 아직 미완
  • analyze_wildcard: 이 속성을 true로 설정하게 되면, 와일드 카드를 검색한다.
    -> 이것도 무슨소리인가 싶었다.
    -> 이 이슈에 왜 이 옵션을 설정해두었는지 설명되어있다. 내용을 바탕으로 이해하면 이렇다. 어떤 형태소 분석기냐에 따라서 제외되는 알파벳들이 있다. 위의 이슈에서는 iphone에서 스패니시 분석기는e를 항상 제외시킨다고 한다. 그러면 iphon으로 토큰화 되어서 분석하게 되고, 원하지 않은 결과를 얻을 수 있다. 이를 방지하기 위해서 토큰화된 양 옆에 와일드 카드가 있다고 가정하고 분석하도록 하는 옵션이다.
    하지만, 디폴트가 false인 것을 보니 특별히 분석기를 바꾸지 않는 이상 쓸 일이 없을 것 같다.

0개의 댓글