8-2. Settings & Mappings - Mappings
1. Dynamic 매핑
동적으로 Mapping이 생성된다면 필드의 값을 보고 타입을 예상한다. 이 때 예상은 가능한 모든 타입중 가장 큰 데이터 타입을 선택한다.
(예 125는 값이 작지만 자연수를 저장하는 데이터 타입 중 가장 큰 long으로 저장된다)
// books 인덱스가 없는 상태에서 도큐먼트 입력
PUT books/_doc/1
{
"title": "Romeo and Juliet",
"author": "William Shakespeare",
"category": "Tragedies",
"publish_date": "1562-12-01T00:00:00",
"pages": 125
}
// books 인덱스의 매핑 확인
GET books/_mapping
//books 인덱스의 매핑 확인 결과
{
"books" : {
"mappings" : {
"properties" : {
"author" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"category" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"pages" : {
"type" : "long"
},
"publish_date" : {
"type" : "date"
},
"title" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
2. 매핑정의
데이터가 입력되어 자동으로 매핑이 생성되기 전에 미리 먼저 인덱스의 매핑을 정의 해 놓으면 정의 해 놓은 매핑에 맞추어 데이터가 입력됩니다. 매핑은 다음과 같이 선언합니다.
// 인덱스의 매핑 정의
PUT <인덱스명>
{
"mappings": {
"properties": {
"<필드명>":{
"type": "<필드 타입>"
… <필드 설정>
}
…
}
}
}
이미 생성된 매핑에서의 필드 추가는 가능하나 삭제나 변경은 불가능 하다.
이는 Object 타입의 내부 필드, 그리고 다중필드에도 동일하게 적용된다.
(간단하게 없는 요소를 입력하면 자동으로 추가가 된다)
기존 매핑에 필드 추가
PUT <인덱스명>/_mapping
{
"properties": {
"<추가할 필드명>": {
"type": "<필드 타입>"
… <필드 설정>
}
}
}
3. Type
- 문자열
- Text : 입력된 문자열을 텀 단위로 쪼개어 Inverted Index 구조를 만듭니다.
- "analyzer" : "<애널라이저명>" - 색인에 사용할 애널라이저를 입력하며 디폴트로는 standard 애널라이저를 사용합니다. 토크나이저, 토큰필터들을 따로 지정할수가 없으며 필요하다면 사용자 정의 애널라이저를 settings에 정의 해 두고 사용합니다.
- "search_analyzer" : "<애널라이저명>" - 기본적으로 text 필드는 match 쿼리로 검색을 할 때 색인에 사용한 동일한 애널라이저로 검색 쿼리를 분석합니다. search_analyzer 를 지정하면 검색시에는 색인에 사용한 애널라이저가 아닌 다른 애널라이저를 사용합니다. 보통 NGram 방식으로 색인을 했을 때는 지정 해 주는 것이 바람직합니다.
- "index" : <true | false> - 디폴트는 true 입니다. false로 설정하면 해당 필드는 역 색인을 만들지 않아 검색이 불가능하게 됩니다.
- "boost" : <숫자 값> - 디폴트는 1 입니다. 값이 1 보다 높으면 풀텍스트 검색 시 해당 필드 스코어 점수에 가중치를 부여합니다. 1보다 낮은 값을 입력하면 가중치가 내려갑니다.
- "fielddata" : <true | false> - 디폴트는 false 입니다. true로 설정하면 해당 필드의 색인된 텀 들을 가지고 집계(aggregation) 또는 정렬(sorting)이 가능합니다. 이 설정은 다이나믹 설정으로 이미 정의된 매핑에 true 또는 false로 다시 적용하는 것이 가능합니다.
- Keyword : 입력된 문자열을 하나의 토큰으로 저장합니다.
- index, boost 설정은 text 필드와 동일하게 동작합니다.
- "doc_values" : <true | false> - 디폴트는 true 입니다. keyword 값들은 기본적으로 집계나 정렬에 메모리를 소모하지 않기 위해 값들을 doc_values 라고 하는 별도의 열 기반 저장소(columnar store)를 만들어 저장합니다. 이 값을 false로 하면 doc_values에 값을 저장하지 않아 집계나 정렬이 불가능해집니다.
- "ignore_above" : <자연수> - 디폴트는 2,147,483,647 이며 다이나믹 매핑으로 생성되면 ignore_above: 256 로 설정이 됩니다. 설정된 길이 이상의 문자열은 색인을 하지 않아 검색이나 집계가 불가능합니다. _source에는 남아있기 때문에 다른 필드 값을 쿼리해서 나온 결과로 가져오는 것은 가능합니다.
- "normalizer" : "<노멀라이저명>" - keyword 필드는 애널라이저를 사용하지 않는 대신 노멀라이저(normalizer) 의 적용이 가능합니다. 노멀라이저는 애널라이저와 유사하게 settings 에서 정의하며 토크나이저는 적용할 수 없고 캐릭터 필터와 토큰 필터만 적용해서 사용이 가능합니다.
- Text : 입력된 문자열을 텀 단위로 쪼개어 Inverted Index 구조를 만듭니다.
- 숫자
- long : 64비트 정수 (-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807)
- integer : 32비트 정수 (-2147483648 ~ 2147483647)
- short : 16비트 정수 (-32768 ~ 32767)
- byte : 8비트 정수 (-128 ~ 127)
- double : 64비트 실수
- float : 32비트 실수
- half_float : 16비트 실수
- scaled_float : 실수형이지만 부동소수점이 아니라 long 형태로 저장하고 옵션으로 소수점 위치를 지정합니다. 통화 (예: $19.99) 같이 소수점 자리가 고정된 값을 표시할 때 유용합니다.
- 공동적으로 적용가능한 설정
- "index", "doc_values", "boost" 옵션들은 text, keyword 필드의 옵션들과 동일합니다.
- "coerce": <true | false> - 디폴트는 true 입니다. 숫자 필드들은 기본적으로 숫자로 이해될 수 있는 값들은 숫자로 변경해서 저장합니다. 예를 들어 integer 필드에 4, "4", 4.5 등을 입력하면 모두 자연수 4로 자동으로 변환되어 저장됩니다. false 로 설정하면 정확한 타입으로 입력되지 않으면 오류가 발생합니다.
- "null_value" : <숫자값> - 필드값이 입력되지 않거나 null 인 경우 해당 필드의 디폴트 값을 지정합니다.
- "ignore_malformed" : <true | false> - 디폴트는 false 입니다. 기본적으로 숫자 필드에 숫자가 아닌 문자나 불린 값이 들어오면 Elasticsearch는 오류를 리턴합니다. true로 설정하게 되면 숫자가 아닌 값이 들어와도 도큐먼트를 정상적으로 저장합니다. 하지만 해당 필드의 값은 _source 에만 저장되고 검색이나 집계에는 무시됩니다.
- scaled_float에서만 사용되는 옵션
- "scaling_factor" : <10의 배수> - scaled_float 를 사용하려면 필수로 지정해야 하는 옵션입니다. 소수점 몇 자리까지 저장할지를 지정합니다. 12.3456 이라는 값을 저장하는 경우 scaling_factor: 10 으로 설정했으면 실제로는 12.3 이 저장됩니다. scaling_factor : 100 으로 설정했으면 12.34 가 저장됩니다.
- 날짜
- 동적으로 인식되는 날짜 형태
- "2019-06-12"
- "2019-06-12T17:13:40"
- "2019-06-12T17:13:40+09:00"
- "2019-06-12T17:13:40.428Z"
- Format을 이용한 사용자정의 Date
- 동적으로 인식되는 날짜 형태
my_date 인덱스 선언
PUT my_date
{
"mappings": {
"properties": {
"date_val": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy/MM/dd||epoch_millis"
}
}
}
}
심볼 |
의미 |
예) 2019-09-12T17:13:07.428+09:00 |
yyyy |
년도 |
2019 |
MM |
월 - 숫자 |
09 |
MMM |
월 - 문자 (3자리) |
Sep |
MMMM |
월 - 문자 (전체) |
September |
dd |
일 |
12 |
a |
오전 / 오후 |
PM |
HH |
시각 (0~23) |
17 |
kk |
시각 (01~24) |
17 |
hh |
시각 (01~12) |
05 |
h |
시각 (1~12) |
5 |
mm |
분 (00~59) |
13 |
m |
분 (0~59) |
13 |
ss |
초 (00~59) |
07 |
s |
초 (0~59) |
7 |
SSS |
밀리초 |
428 |
Z |
타임존 |
+0900 / +09:00 |
e |
요일 (숫자 1:월 ~ 7:일) |
4 |
E |
요일 (텍스트) |
Thu |
- Boolean
- 문자열 "True"로 입력되도 True로 해석되어 저장된다.
- 옵션
- "doc_values", "index" 옵션들은 문자열, 숫자 필드와 기능이 동일합니다.
- "null_value" : <true | false> - 필드가 존재하지 않거나 값이 null 일 때 디폴트 값을 지정합니다. 지정하지 않으면 불리언 필드가 없거나 값이 null인 경우 존재하지 않는 것으로 처리되어 true / false 모두 쿼리나 집계에 나타나지 않습니다.
- Object
- 여러 하위정보를 가지고 있는경우 Object로 사용된다. (하위 Type을 지정하면 자동으로 Object로 생성된다)
- Elasticsearch에는 따로 배열(array) 타입의 필드를 선언하지 않으며, 필드 타입의 값만 일치하면 다음과 같이 값을 배열로도 넣을 수 있다.
- { "title": [ "Romeo and Juliet", "Hamlet" ] }
// 매핑에 object 타입 characters 필드 선언
PUT movie
{
"mappings": {
"properties": {
"characters": {
"properties": {
"name": {
"type": "text"
},
"age": {
"type": "byte"
},
"side": {
"type": "keyword"
}
}
}
}
}
}
// characters 하위의 name 필드 쿼리
GET movie/_search
{
"query": {
"match": {
"characters.name": "Iron Man"
}
}
}
// 다른 예제이긴 하지만 아래와 같이 Array 화 된 Object에서 다음과 같이 검색 가능
// characters 하위 필드의 name: Loki, side: villain 검색
GET movie/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"characters.name": "Loki"
}
},
{
"match": {
"characters.side": "villain"
}
}
]
}
}
}
- Object (Nested)
- nested 쿼리로 검색하면 nested 필드의 내부에 있는 값 들을 모두 별개의 도큐먼트로 취급합니다.
// nested 쿼리로 characters 하위 필드의 name: Loki, side: villain 검색
GET movie/_search
{
"query": {
"nested": {
"path": "characters",
"query": {
"bool": {
"must": [
{
"match": {
"characters.name": "Loki"
}
},
{
"match": {
"characters.side": "villain"
}
}
]
}
}
}
}
}
7.2.6 위치 정보 - Geo
이 문서의 허가되지 않은 무단 복제나 배포 및 출판을 금지합니다. 본 문서의 내용 및 도표 등을 인용하고자 하는 경우 출처를 명시하고 김종민(kimjmin@gmail.com)에게 사용 내용을 알려주시기 바랍�
esbook.kimjmin.net
- IP - IPv4 or IPv6
- Range - 숫자나 날짜, IP 등을 시작과 끝이 있는 2차원의 범위 형태로 저장
- Range 종류
- integer_range
- float_range
- long_range
- double_range
- date_range
- ip_range
- Range 옵션
- within : 도큐먼트 범위 값이 쿼리한 범위 안에 완전히 포함되는 도큐먼트들을 가져옵니다.
- contains : within과 반대로 쿼리 범위가 도큐먼트 범위 값 안에 완전히 포함되는 도큐먼트들을 가져옵니다.
- Intersects : 도큐먼트 범위 값과 쿼리 범위에 공통적인 부분이 있는 도큐먼트들을 가져옵니다.
- Range 종류
예제
// blogs 인덱스 선언하면서 각 필드의 text, keyword 매핑 설정
PUT blogs
{
"settings": {
"analysis": {
"analyzer": {
"engram_a": {
"tokenizer": "standard",
"filter": [ "lowercase", "engram_f" ]
}
},
"filter": {
"engram_f": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 5
}
},
"normalizer": {
"norm_low": {
"type": "custom",
"filter": [ "lowercase", "asciifolding" ]
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"boost": 2,
"fields": {
"keyword": {
"type": "keyword",
"normalizer": "norm_low"
}
}
},
"author": {
"type": "text",
"analyzer": "engram_a",
"search_analyzer": "standard",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"synopsis": {
"type": "text",
"fielddata": true
},
"category": {
"type": "keyword"
},
"content": {
"type": "text",
"index": false
}
}
}
}