- 기본 쿼리 문, 타입, API 제외 모르는 것 위주로 정리
- 참고
1) 필드 타입
- Object / Nested Type

- object 필드 값들은 실제로 하나의 Document 안에 전부 포함되어 있다.
- nested 필드 값들은 내부적으로 별도의 Document로 분리되어 저장되며 쿼리 결과에서 상위 Document와 합쳐져서 보여지게 된다.
- 위치 정보 필드 Geo Point Type
Geo Point 는 위도(latitude)와 경도(longitude) 두 개의 실수 값을 가지고 지도 위의 한 점을 나타내는 값입니다. Geo Point 필드의 값들은 다음과 같이 다양한 방법으로 입력이 가능합니다.
object 형식으로 geo_point 입력PUT my_locations/_doc/1{"location": {"lat": 41.12,"lon": -71.34}}
text 형식으로 geo_point 입력PUT my_index/_doc/2{"location": "41.12,-71.34"}
geohash 형식으로 geo_point 입력PUT my_index/_doc/3{"location": "drm3btev3e86"}
실수의 배열 형식으로 geo_point 입력PUT my_index/_doc/4{"location": [-71.34,41.12]}
Geo Point 필드는 매핑에서 다음과 같이 "type": "geo_point" 로 선언합니다.
object 형식으로 geo_point 입력PUT my_geo{"mappings": {"properties": {"location": {"type": "geo_point"}}}}
- IP , Range, Binary Type
IP
IP 주소 형식을 저장합니다. 매핑은 "type": "ip" 으로 선언합니다. 값은 "192.168.1.1" 같은 IPv4 형식과 "0:0:0:0:0:ffff:c0a8:105" 같은 IPv6 형식을 문자열 처럼 입력합니다.
Range
숫자나 날짜, IP 등을 시작과 끝이 있는 2차원의 범위 형태로 저장합니다. 매팽의 "type" 에 선언 가능한 값은 integer_range, float_range, long_range, double_range, date_range, ip_range 들이 있습니다. 데이터의 범위는 다음과 같이 gt, gte, lt, lte 를 사용해서 지정합니다.
integer_range 와 date_range 타입의 필드 선언PUT my_range{"mappings": {"properties": {"amount": {"type": "integer_range"},"days": {"type": "date_range"}}}}
쿼리를 테스트 하기 위해 먼저 다음 도큐먼트를 입력하겠습니다.
integer_range, date_range 타입의 값을 가진 도큐먼트 입력PUT my_range/_doc/1{"amount": {"gte": 19,"lt": 28},"days": {"gt": "2019-06-01T09:00:00","lt": "2019-06-20"}}
Range 필드의 쿼리는 일반적인 숫자나 날짜 처럼 range 쿼리를 사용합니다. 다만 범위 데이터를 range 쿼리로 검색 할 때는 추가로 relation 옵션의 값을 입력해야 하며 입력하지 않으면 오류가 납니다. relation 옵션에 지정 가능한 값은 within, contains, intersects 3가지가 있습니다.
- within : 도큐먼트 범위 값이 쿼리한 범위 안에 완전히 포함되는 도큐먼트들을 가져옵니다.
- contains : within과 반대로 쿼리 범위가 도큐먼트 범위 값 안에 완전히 포함되는 도큐먼트들을 가져옵니다.
- Intersects : 도큐먼트 범위 값과 쿼리 범위에 공통적인 부분이 있는 도큐먼트들을 가져옵니다.
사용 예제는 다음과 같습니다.
request
"relation": "intersects" 으로 range 쿼리GET my_range/_search{"query": {"range": {"amount": {"gte": "16","lte": "25","relation": "intersects"}}}}
다른 값을 가진 도큐먼트를 더 입력하고 relation 값을 contains, within 으로 변경 해 가면서 더 실습 해 보시기 바랍니다.
response
"relation": "intersects" 으로 range 쿼리 결과{"took" : 950,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 1,"relation" : "eq"},"max_score" : 1.0,"hits" : [{"_index" : "my_range","_type" : "_doc","_id" : "1","_score" : 1.0,"_source" : {"amount" : {"gte" : 19,"lt" : 28},"days" : {"gt" : "2019-06-01T09:00:00","lt" : "2019-06-20"}}}]}}
여행이나 출장 정보를 담은 도큐먼트가 있다면 시작일, 종료일 두 필드를 지정하는 대신 출장기간 이라는 date_range 타입의 단일 필드로 값을 저장해서 더욱 편하고 유용하게 사용할 수 있습니다.
Binary
"type": "binary" 로 지정해서 시스템 파일이나 이미지 정보 같은 바이너리 값을 저장할 수 있습니다. binary 필드는 기본적으로 색인이 되지 않아 검색이나 집계가 불가능하고 _source에만 남아 있습니다.
바이너리 정보들은 일반적으로 용량이 크기 때문에 elasticsearch 도큐먼트에 저장하는 것은 불필요한 저장소와 통신 데이터의 낭비가 될 수 있습니다. 가능하면 바이너리 데이터의 저장은 S3 또는 HDFS 같은 저렴한 저장소를 이용하고 elasticsearch 도큐먼트에는 해당 자원에 접근 가능한 키 또는 URL 등만 저장해서 따로 가져오도록 하는 것이 바람직합니다.
지금까지 설명한 필드 외에도 수많은 종류의 필드 타입들이 있습니다. 새 버전이 나올 때 마다 새로운 필드 타입들이 추가되거나 기존에 있던 타입들의 사용이 만료되고 있기 때문에 항상 공식 도큐먼트를 잘 참고하시기 바랍니다.
2) 검색 쿼리
- match , match_all (_search 와 동일)
- match 는 Full-Text-Search에 이용
- match 쿼리는 풀 텍스트 검색에 사용되는 가장 일반적인 쿼리
- message 필드를 이용해서 해당 message가 포함되어있는 모든 문서를 검색
match 쿼리로 message 필드에서 dog 검색GET my_index/_search{"query": {"match": {"message": "dog"}}}
- 검색어 조건 변경 필드 operator 옵션 이용 ( <필드 명>: { "query":<검색어>, "operator": } )
match 쿼리 AND 조건으로 quick dog 검색GET my_index/_search{"query": {"match": {"message": {"query": "quick dog","operator": "and"}}}}
- 위의 예시의 반대로 공백 전체를 검색하기 위한 쿼리 match_pharse 이용 ( ex) quick dog 사이의 공백)
- slop 이라는 옵션을 이용하여 slop에 지정된 값 만큼 단어 사이에 다른 검색어가 끼어드는 것을 허용
match_phrase 쿼리로 "lazy dog" 구문 검색GET my_index/_search{"query": {"match_phrase": {"message": "lazy dog"}}}
match_phrase 쿼리에 slop:1 로 "lazy dog" 구문 검색GET my_index/_search{"query": {"match_phrase": {"message": {"query": "lazy dog","slop": 1}}}}response ....."message" : "Lazy jumping dog"
- Filter : score 값에 영향을 주지 않도록 제어할 때 사용
지금까지 살펴본 풀 텍스트 검색은 스코어 점수 기반으로 정확도(relevancy)가 높은 결과부터 가져옵니다. Elasticsearch는 정확도를 고려하는 풀 텍스트 외에도 검색 조건의 참 / 거짓 여부만 판별해서 결과를 가져오는 것이 가능합니다. 풀 텍스트와 상반되는 이 특성을 정확값(Exact Value) 이라고 하는데 말 그대로 값이 정확히 일치 하는지의 여부 만을 따지는 검색입니다. Exact Value 에는 term, range 와 같은 쿼리들이 이 부분에 속하며, 스코어를 계산하지 않기 때문에 보통 bool 쿼리의 filter 내부에서 사용하게 됩니다.
세부 검색 ex)
must 로 fox 검색 후 must_not 으로 dog 제거GET my_index/_search{"query": {"bool": {"must": [{"match": {"message": "fox"}}],"filter": [{"bool": {"must_not": [{"match": {"message": "dog"}}]}}]}}}
- keyword
문자열 데이터는 keyword 형식으로 저장하여 정확 값 검색이 가능합니다. 아래의 쿼리는 message 필드 값이 "Brown fox brown dog" 문자열과 공백, 대소문자까지 정확히 일치하는 데이터 만을 결과로 리턴
request
keyword 필드 검색GET my_index/_search{"query": {"bool": {"filter": [{"match": {"message.keyword": "Brown fox brown dog"}}]}}}
response
keyword 필드 검색 결과{"took" : 0,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 1,"relation" : "eq"},"max_score" : 0.0,"hits" : [{"_index" : "my_index","_type" : "_doc","_id" : "4","_score" : 0.0,"_source" : {"message" : "Brown fox brown dog"}}]}}
keyword 타입으로 저장된 필드는 스코어를 계산하지 않고 정확 값의 일치 여부 만을 따지기 때문에 스코어가 "_score" : 0.0 으로 나오게 됩니다. 스코어를 계산하지 않기 때문에 keyword 값을 검색 할 때는 filter 구문 안에 넣도록 합니다.
3) Bulk API
여러 명령을 배치로 수행하기 위해서 _bulk API의 사용이 가능 _bulk API로 index, create, update, delete의 동작이 가능하며 delete를 제외하고는 명령문과 데이터 문을 한 줄씩 순서대로 입력해야 한다. delete는 내용 입력이 필요 없기 때문에 명령문만 있다.
_bulk 의 명령문과 데이터 문은 반드시 한 줄 안에 입력이 되어야 하며 줄 바꿈을 허용 하지 않음.
다음은 _bulk 명령을 실행한 예제입니다. 각 명령의 결과가 items에 배열로 리턴
_bulk 명령 실행POST _bulk{"index":{"_index":"test", "_id":"1"}}{"field":"value one"}{"index":{"_index":"test", "_id":"2"}}{"field":"value two"}{"delete":{"_index":"test", "_id":"2"}}{"create":{"_index":"test", "_id":"3"}}{"field":"value three"}{"update":{"_index":"test", "_id":"1"}}{"doc":{"field":"value two"}}

모든 명령이 동일한 인덱스에서 수행되는 경우에는 아래와 같이 <인덱스명>/_bulk 형식으로도 사용이 가능하다.

인덱스 단위로 _bulk 사용
벌크 동작은 따로따로 수행하는 것 보다 속도가 훨씬 빠르다. 특히 대량의 데이터를 입력 할 때는 반드시 _bulk API를 사용해야 불필요한 오버헤드가 없다. Logstash 와 Beats 그리고 Elastic 웹페이지에서 제공하는 대부분의 언어 별 클라이언트에서는 데이터를 입력할 때 _bulk를 사용하도록 개발되어 있다.
4) Update API
- upsert document
