-
ES - 데이터 검색🔍 elastic search 2022. 9. 21. 19:55
ES는 검색에 사용하기 위한 데이터를 저장할 때 Term 으로 분석 과정을 거쳐 저장하기 때문에 검색 시,
대소문자, 단수나 복수, 원형 여부와 상관없이 검색이 가능하다.
- 이러한 특징을 Full Text Search ( = 전문 검색) 이라고 한다.
Query DSL
Elasticsearch는 검색을 위한 쿼리 기능을 제공
- 이런 데이터 시스템에서 제공하는 쿼리 기능을 Query DSL(Domain Specific Language) 이라고 이야기 한다.
- Elasticsearch의 Query DSL은 모두 JSON 형식으로 입력
검색 API를 사용해 Elastic search 데이터 스트림 또는 인덱스에 저장된 데이터를 검색하고 집계할 수 있다.
- API 쿼리 요청 본문 매개 변수는 Query DSL로 작성된 쿼리를 사용
두 가지로 구분할 수 있다.
- 리프 쿼리 절
- 리프 쿼리 절은 ‘match’, ‘term’ 또는 ‘range’ 쿼리와 같은 특정 필드에서 특정 값을 찾는다.
- 이러한 쿼리는 스스로 사용 가능
- 복합 쿼리 절
- 복합 쿼리 절은 다른 리프 또는 복합 쿼리를 감싸며 논리적인 방식으로 여러 쿼리를 결합하거나 동작을 변경하는데 사용
관련성 점수
ES는 검색을 했을 때 검색 결과에 대해서 일치하는 정도 를 측정하는 점수를 가지고, 해당 점수에 따라 검색 결과를 정렬
관련성 점수 : 검색 API를 호출했을 때 _score 필드의 값
- 점수가 높을 수록 문서의 관련성이 높다.
- 각 쿼리 유형은 관련성 점수를 다르게 계산할 수 있다.
- 점수 계산은 쿼리 절이 쿼리 컨텍스트에서 실행되는지, 필터 컨텍스트에서 실행되는지에 따라 달라진다.
쿼리 컨텍스트 / 필터 컨텍스트
쿼리 컨텍스트 (Query context)
- 쿼리 절이 “쿼리와 문서와 얼마나 잘 일치 하는가?” 라는 질문에 답한다.
- _score를 통해 문서가 다른 문서와 비교하여 쿼리와 얼마나 일치하는지를 계산
필터 컨텍스트 (Filter context)
- 쿼리 절이 “쿼리가 문서와 일치하는가?” 라는 질문에 답한다.
- _score는 계산하지 않는다.
- 대부분 필터링을 위해 사용
정확한 검색이 아닌 유사검색( 문자 검색 )과 같은 것은 query context 를 사용하고 정확한 검색을 원할 때는 filter context 를 사용!
실습
index 세팅
foods 인덱스에 name(이름, text), price(가격, integer), count(수량, integer), store(가게, keyword) 이 매핑
PUT /foods { "mappings": { "properties": { "name": { "type": "text" }, "price": { "type": "integer" }, "count": { "type": "integer" }, "store": { "type": "keyword" } } } } POST _bulk {"index":{"_index":"foods", "_type" : "_doc", "_id":"1"}} {"name":"음식1", "price": 1000, "count": 90, "store": "A"} {"index":{"_index":"foods", "_type" : "_doc", "_id":"2"}} {"name":"음식23", "price": 10000, "count": 90, "store": "A"} {"index":{"_index":"foods", "_type" : "_doc", "_id":"3"}} {"name":"음식3", "price": 15000, "count": 80, "store": "B"} {"index":{"_index":"foods", "_type" : "_doc", "_id":"4"}} {"name":"음식4", "price": 16000, "count": 74, "store": "B"} {"index":{"_index":"foods", "_type" : "_doc", "_id":"5"}} {"name":"음식43", "price": 17000, "count": 50, "store": "A"}
// 인덱스 만들기 curl curl -XPUT 'localhost:9200/test_index' -H 'Content-type:application/json' -d '{ "mappings": { "properties": {"text_name":{ "type": "text"},"keyword_name": {"type":"keyword"}}}}'
// 인덱스 만들어졌는지 확인 curl -XGET 'localhost:9200/test_index/'
// bulk api curl curl -X POST "localhost:9200/foods/_bulk?pretty" -H 'Content-Type: application/json' -d' { "index" : { "_index" : "test", "_id" : "1" } } { "field1" : "value1" } { "delete" : { "_index" : "test", "_id" : "2" } } { "create" : { "_index" : "test", "_id" : "3" } } { "field1" : "value3" } { "update" : {"_id" : "1", "_index" : "test"} } { "doc" : {"field2" : "value2"} } '
Full Text 쿼리
- 분석된 텍스트 필드를 검색
- 인덱싱 중에 필드에 적용된 분석기와 동일한 분석기를 사용하여 처리
쿼리 설명 match - 전체 텍스트 검색을 수행하기 위한 표준 쿼리
- 주어진 텍스트는 검색하기 전 분석된다.
- 띄워쓰기가 포함되서 값이 주어지는 경우 OR 로 조회한다.match_all 별다른 조건 없이 해당 인덱스의 모든 도큐먼트를 검색한다. match_phrase 입력된 검색어를 순서까지 고려해 검색을 수행한다. query_string - URL 검색에 사용하는 Lucene의 검색 문법을 본문 검색에 이용하고 싶을 때 사용한다.
- 구문을 사용하여 AND 또는 NOT와 같은 연산자를 기반으로 제공된 쿼리 문자열을 구문 분석 및 분할한다.
- 다음 쿼리는 일치하는 문서를 반환하기 전에 분할된 각 텍스트를 독립적으로 분석한다.1. match_all
GET foods/_search { "query":{ "match_all":{ } } } curl -XPOST 'localhost:9200/foods/_search?pretty' -H 'Content-Type: application/json' -d'{ ✔ │ base "query": { "match_all": {} } }'
해당 인덱스에 있는 모든 데이터가 노출
2. match
- 공백이 OR 연산자로 작동한다.
GET foods/_search { "query": { "match": { "name": "음식1" } } } curl -X GET "localhost:9200/foods/_search?pretty" -H 'Content-Type: application/json' -d' { "query": { "match": { "name": "음식1 음식3" } } } ' // 음식1 OR 음식3 으로 검색된다.
이를 AND로 바꾸고 싶다면 operator를 명시해 준다.
curl -X GET "localhost:9200/foods/_search?pretty" -H 'Content-Type: application/json' -d' { "query": { "match": { "name": "음식1 음식3", "operator": "and" } } } '
3. match_phrase
match 쿼리와 거의 동일하게 작동하지만 순서까지 필터링 한다.
ex) my name 이라는 값이 있다면 my name 이라고 검색해야 값이 나온다
- name my 으로 검색하는 경우는 값 ❌
GET /_search { "query": { "match_phrase": { "name": "음식1 음식3" } } } curl -X GET "localhost:9200/foods/_search?pretty" -H 'Content-Type: application/json' -d' { "query": { "match_phrase": { "name": "음식1 음식3" } } } '
4. query_string
GET /_search { "query": { "query_string": { "query": "(new york city) OR (big apple)", "default_field": "content" } } } curl -X GET "localhost:9200/foods/_search?pretty" -H 'Content-Type: application/json' -d' { "query": { "query_string": { "query": "음식1 OR 음식3", "default_field": "name" } } } '
내장된 쿼리 분석기를 이용하는 질의 작성 가능
bool 복합 쿼리
- Lucene BooleanQuery 에 매핑
- 여러 쿼리를 조합하기 위해서는 상위에 bool 쿼리를 사용하고 그 안에 다른 쿼리들을 넣어 사용
1. must
POST _search { "query": { "bool" : { "must" : { "match" : { "name" : "음식1" } } } } }
2. filter
POST _search { "query": { "bool" : { "filter": { "match" : { "name" : "음식1" } } } } }
3. should
POST _search { "query": { "bool" : { "should" : [ { "match" : { "name" : "음식1" }, { "match" : { "name" : "음식3" } } ] } } }
- should를 단독으로 사용할 때
- OR로 적용이 된다.
POST _search { "query": { "bool" : { "should" : [ { "match" : { "name" : "음식1" }, { "match" : { "name" : "음식3" } } ], "must" : [ { "match" : { "store" : "A" } ] } } }
- 다른 쿼리와 복합적으로 사용하는 경우 - score로 적용
- 다른 쿼리에 속한 값이 노출
- should에 있는 조건인 경우 더 높은 score를 부여한다.
Term-level 쿼리
- Analyer를 사용하지 않고 정확한 값을 조회하는 쿼리
- 검색어를 분석하지 않는다.
- keyword 타입을 대상으로 한다.
쿼리 설명 exists 실제 값이 존재하는 문서만 반환 fuzzy Levenshtein 편집 거리로 측정한 검색어와 유사한 용어를 포함하는 문서를 반환 range 범위 내 데이터를 리턴하는 쿼리 term 제공된 필드에 정확한 용어가 포함된 문서를 반환 terms 제공된 필드에 하나 이상의 정확한 용어가 포함된 문서를 반환 wildcard 와일드카드 패턴과 일치하는 용어를 포함하는 문서를 반환 - exist
- score 에 값이 있는 도큐먼트만 노출
GET /_search { "query": { "exists": { "field": "store" } } }
- term
- 별도의 분석 작업 수행 하지않고 입력된 텍스트가 존재하는 문서를 찾는다.
GET /_search { "query": { "term": { "name": { "value": "음식1" } } } }
- terms
- term과 동일하게 작동하지만, 여러개의 검색어를 한번에 찾을 수 있다.
GET /_search { "query": { "terms": { "name": [ "음식1", "음식2" ], } } }
- wildcard
- 검색어가 와일드카드와 일치하는 구문을 찾고, 입력된 검색어는 형태소 분석이 이루어지지 않는다.
→ 음…….1 인 document를 찾는다.GET /_search { "query": { "wildcard": { "name": { "value": "음*1" } } } }
참고자료
'🔍 elastic search' 카테고리의 다른 글
ES - Aggregations (0) 2022.09.22 ES - 텍스트 분석 (0) 2022.09.22 ES - 기본 API (0) 2022.09.21 Docker로 ES 설치하기 (1) 2022.09.21 ElasticSearch (0) 2022.09.20