7. 인덱스 설정과 매핑
- 데이터의 저장 및 검색 방법에 대한 설정이나 사용자 정의 애널라이저는 인덱스 단위로 저장된다.
7.1 설정 - Settings
- 인덱스는 두 개의 정보 단위, settings 와 mappings로 이루어진다.
- settings 또는 mappings 를 보는 보는 방법은 각각 _settings API 나 _mappings API를 사용한다.
- 대부분의 설정은 한 번 지정하면 변경할 수 없다.
- 샤드와 복제본 수 설정
- number_of_shards와 number_of_replicas 라는 이름으로 "settings" - "index" 아래에 설정한다.
- PUT my_index
{
"settings": {
"index": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}
} - shrink API 또는 split API를 이용해서 샤드 수를 변경할 수 있으나, 복잡하므로 변경할 수 없다고 생각하자.
- 복제본 수는 변경 가능하다.
- refresh_interval: 세그먼트가 만들어지는 리프레시 타임을 설정한다. 기본은 1초이다.
- PUT my_index
{
"settings": {
"refresh_interval": "30s"
}
}
- PUT my_index
- analyzer, tokenizer, filter
- 애널라이저, 토크나이저 필터 등은 "settings"-"analysis" 하위에 지정한다.
- PUT my_index
{
"settings": {
"analysis": {
"analyzer": { ## 애널라이저 지정
"my_analyzer": {
"type": "custom",
"char_flter": [ "...", "..." ... ]
"tokenizer": "...",
"filter": [ "...", "..." ... ]
}
},
"char_filter":{ ## 캐릭터 필터 지정
"my_char_filter":{
"type": "…"
...
}
}
"tokenizer": { ## 토크나이저
"my_tokenizer":{
"type": "…"
...
}
},
"filter": { ## 토큰 필터
"my_token_filter": {
"type": "…"
...
}
}
}
}
}
- analysis는 변경 불가능하다. 변경이 필요할 시 재색인 과정을 거치자.
7.2 매핑 - Mappings
- 엘라스틱서치는 동적 매핑을 지원하기 때문에 도큐먼트 추가 시 자동으로 매핑이 생성된다.
- 매핑 정보는 "mappings" - "properties" 아래에 지정한다.
- PUT books
{
"mappings": {
"properties": {
"category": {
"type": "keyword"
},
"pages": {
"type": "byte"
},
"title": {
"type": "text"
}
}
}
} - 이미 만들어진 필드를 삭제하거나 타입 및 설정 값을 변경할 수는 없다.
7.2.1 문자열 - text, keyword
- 매핑에 필드를 정의하지 않으면 동적 문자열 필드가 생성될 때 text, keyword 필드가 다중 필드로 같이 생성된다.
- text: 풀 텍스트 검색에 사용될 문자열. 역 색인 구조를 생성한다.
- "analyzer": "<애널라이저명>" - 색인에 사용할 애널라이저를 지정한다.
- "search_analyzer":"<애널라이저명>" - 검색 시 색인 할때와 다른 애널라이저를 사용할 수 있다. Ngram 방식 사용시 지정이 바람직하다.
- "index" : false로 지정시 해당 필드는 역색인 구조를 만들 지 않는다.(default: true)
- "boost": 해당 필드 스코어 점수에 가중치를 부여한다. 1보다 낮은 값이면 가중치가 내려간다.(default: 1)
- 인덱스 타임 boost는 5.0부터 deprecated. 쿼리 시에 사용하자.
- "fielddata": true로 사용하면 집계 및 정렬이 가능하나 메모리를 많이 사용한다.(default: false)
- keyword: 입력된 문자열을 하나의 토큰으로 저장한다. 보통 집계, 정렬에 사용한다.
- index, boost: text와 동일
- "doc_values": false 시 집계, 정렬을 위한 열기반 저장소를 생성하지 않아 집계 및 정렬이 불가능하다.(default: true)
- "ignore_above": <자연수> - 해당 길이 이상의 문자열은 색인하지 않아 검색과 집계가 불가능하다.(default = Integer.MAX_VALUE, 동적 매핑시 256)
- "nomalizer": "<노멀라이저명>" - 노멀라이저를 지정한다. 노멀라이저는 애널라이저-토크나이저이다.
- PUT blogs
{
"settings": {
"analysis": { ## analysis 아래에는 analyzer, filter, char_filter, nomalizer 가 있다.
"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, ## deprecated
"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
}
}
}
}
7.2.2 숫자
- long, integer, short, byte, double, float 등 기본 타입을 지원한다.
- half_float: 16비트 실수
- scaled_float: long 형태로 저장하고 소수점 위치를 지정한다.
- "index", "doc_value", "boost" 는 문자와 동일
- "coerce": <true|false> - 자동 타입 변환 (integer에 4.5 -> 4로 색인, 저장은 4.5, default는 true)
- "null_value": <숫자값> - null 일시 default 값 지정
- "ignore_malformed": <true|false> : true 시 숫자가 아닌 값이 들어와도 저장, 검색 및 집계에는 무시 (default는 false)
- "scaled_float" 사용시
- "scaling_factor": <10의 배수> - 예를 12.3456이란 값이 factor가 10일 경우 12.3으로 저장된다.
7.2.3 날짜
- ISO8601 형식을 따라 입력한다.
- "2019-06-12"
- "2019-06-12T17:13:40+09:00"
- "2019-06-12T17:13:40+09:00"
- "2019-06-12T17:13:40.428Z"
- epoch_mills, epoch_seconds, basic_date, strict_date_time도 사용가능
- 이 외에는 text, keyword로 저장된다.
- "doc_value", "index", "null_value", "ignore_malfomed"는 동일하게 동작
- "format": "<문자열||문자열||..>"로 매핑 시 포맷팅
- PUT my_date
{
"mappings": {
"properties": {
"date_val": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy/MM/dd||epoch_millis"
}
}
}
}
GET my_date/_search
{
"query": {
"range": {
"date_val": {
"gt": "2019/09/10",
"lt": 1568332800000
}
}
}
} - 입력과 검색 포맷이 달라도 잘 동작한다.
7.2.4 불리언
- "true"라고 입력해도 true로 해석된다. 일반적으로 term 쿼리를 이용해서 검색한다.
- "doc_value", "index" : 동일하게 동작한다.
- "null_value": <true|false> - 지정하지 않으면 불리언필드가 없거나 null인 경우 존재하지 않는 것으로 처리되어 해당 도큐먼트는 쿼리나 집계에 나타나지 않는다.
7.2.5 Object와 Nested
- Object: 복합 값 필드
- PUT movie
{
"mappings": {
"properties": {
"characters": { ## 필드 이름
"properties": { ## 필드 이름 하위에 다시 properties가 들어간다.
"name": {
"type": "text"
},
"age": {
"type": "byte"
},
"side": {
"type": "keyword"
}
}
}
}
}
}
GET movie/_search
{
"query": {
"match": {
"characters.name": "Iron Man" ## 마침표를 이용해서 접근한다.
}
}
} - PUT movie/_doc/2
{
"title": "The Avengers",
"characters": [ ## 여러 명의 캐릭터를 배열로 넣는다.
{
"name": "Iron Man",
"side": "superhero"
},
{
"name": "Loki",
"side": "villain"
}
]
}
PUT movie/_doc/3
{
"title": "Avengers: Infinity War",
"characters": [
{
"name": "Loki",
"side": "superhero"
},
{
"name": "Thanos",
"side": "villain"
}
]
} - 엘라스틱서치는 별도로 배열 필드를 저장하지 않고 그냥 배열을 입력값으로 넣어도 된다.
- 역 색인에서는 object의 하위 필드는 모두 상위 이름과 함께 펼쳐져서 한 필드로 저장된다.
- 따라서 이 경우 id:2 에는 character.name에는 [아이언맨,로키]가, character.side에는 [superhero, villan]이 포함되어 있는 것으로 역 색인 구조를 만든다.
- 따라서 다음과 같이 쿼리하는 경우
- GET movie/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"characters.name": "Loki"
}
},
{
"match": {
"characters.side": "villain"
}
}
]
}
}
} - id 2,3 문서가 동시에 검색된다.(둘다 로키와 빌런이 있으므로)
- PUT movie
- Nested: object 타입 필드에 있는 여러 object 값들이 서로 다른 역색인 구조를 사용해야할때 nested 타입이 필요하다.
- PUT movie
{
"mappings": {
"properties": {
"characters": {
"type": "nested", ## nested 타입으로 명시
"properties": { ## object와 마찬가지로 필드명 아래 "properties"가 있다.
"name": {
"type": "text"
},
"side": {
"type": "keyword"
}
}
}
}
}
} - 검색할 때도 nested 명시가 필요하다.
- GET movie/_search
{
"query": {
"nested": { ## nested 쿼리
"path": "characters", ## nested로 정의된 필드 명시
"query": {
"bool": {
"must": [
{
"match": {
"characters.name": "Loki"
}
},
{
"match": {
"characters.side": "villain"
}
}
]
}
}
}
}
} - nested 필드 값은 내부적으로 별도의 도큐먼트로 분리되어 저장되며 쿼리 결과에서 상위 도큐먼트와 합쳐져서 보여지게 된다.
- PUT movie
7.2.6 위치정보 - Geo
- Geo Point
- 위도(latitude), 경도(longitude) 두 실수를 가지고 지도 위의 한 점을 나타낸다.
- PUT my_locations/_doc/1
{
"location": {
"lat": 41.12,
"lon": -71.34
}
} - geohash를 사용할 수도 있다.
- PUT my_index/_doc/3
{
"location": "drm3btev3e86"
} - 매핑은 "geo_point"로 선언한다.
- PUT my_geo
{
"mappings": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
} - Geo Point는 반드시 사전에 인덱스 매핑이 필요하다.
- geo_bounding_box 쿼리
- 왼쪽 위와 오른쪽 아래의 좌표 값을 설정해서 네모 형태로 검색한다.
- GET my_geo/_search
{
"query": {
"geo_bounding_box": {
"location": {
"bottom_right": {
"lat": 37.4899,
"lon": 127.0388
},
"top_left": {
"lat": 37.5779,
"lon": 126.9617
}
}
}
}
}
- geo_distance 쿼리
- distance를 반지름으로 하는 원형으로 검색한다.
- GET my_geo/_search
{
"query": {
"geo_distance": {
"distance": "5km",
"location": {
"lat": 37.5358,
"lon": 126.9559
}
}
}
}
- Geo_Shape
- 선 면등의 2차원 값을 지정하고 쿼리할 수 있다.
- PUT my_shape
{
"mappings": {
"properties": {
"location": {
"type": "geo_shape" # 필드 매핑시 geo_shape
}
}
}
} - 입력 데이터 type에는 "point ,"multipoint", "linestring","multilinestring","polygon","multipolygon","envelope"가 있다.
- geo_shape 쿼리
- geo shpae 타입의 값을 검색할려면 geo_shape 쿼리를 사용해야 한다.
- GET my_shape/_search
{
"query": {
"geo_shape": {
"location": {
"shape": {
"type": "envelope",
"coordinates": [
[ 126.9687, 37.58 ],
[ 126.99, 37.5543 ]
]
},
"relation": "intersects"
}
}
}
} - intersects: 위의 영역에 조금이라도 걸쳐있는 곳이 검색
- within: 쿼리 영역에 완전히 포함되어 있어야 한다.
- disjoint: 쿼리 영역 바깥에 있어야 한다.
7.2.7 기타 필드 타입 - IP, Range, Binary
- IP : ip 형식을 저장한다.
- range: 숫자나 날짜, IP 등을 시작과 끝이 있는 2차원 범위 형태로 저장한다.
- PUT my_range
{
"mappings": {
"properties": {
"amount": {
"type": "integer_range"
},
"days": {
"type": "date_range"
}
}
}
}
PUT my_range/_doc/1
{
"amount": {
"gte": 19,
"lt": 28
},
"days": {
"gt": "2019-06-01T09:00:00",
"lt": "2019-06-20"
}
}
GET my_range/_search
{
"query": {
"range": {
"amount": {
"gte": "16",
"lte": "25",
"relation": "intersects"
}
}
}
} - 검색 시 relation 옵션은 필수이다.
- within: 도큐먼트 범위가 검색 범위 안에 완전히 포함되는 경우(검색이 넓다.)
- cotains: 검색 범위가 도큐먼트 범위 안에 포함되는 경우(도큐먼트가 넓다.)
- intersects: 공통 부분이 있는 경우
- PUT my_range
- Binary: 바이너리 값을 저장할 수 있으나 색인되지 않는다.
7.3 멀티 필드 - Multi Field
- 하나의 필드 값을 여러 개의 역 색인 및 docs_values 들로 저장할 수 있는 멀티 필드 기능이 있다.
- PUT my_index
{
"mappings": {
"properties": {
"<필드명1>": {
"type": "text",
"fields": { # 필드 아래에 새로 필드를 정의힌다.
"<필드명2>": {
"type": "<타입>"
}
}
}
}
}
} - PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"nori_analyzer": {
"tokenizer": "nori_tokenizer"
}
}
}
},
"mappings": {
"properties": {
"message": {
"type": "text",
"fields": {
"english": {
"type": "text",
"analyzer": "english" ## 다른 애널라이저를 사용한다.
},
"nori": {
"type": "text",
"analyzer": "nori_analyzer" ## nori 애널라이저 사용
}
}
}
}
}
} - 다국어 도큐먼트를 분석할 때 사용된다.
'엘라스틱서치' 카테고리의 다른 글
엘라스틱서치와 추천 - More Like This 쿼리 (0) | 2021.09.20 |
---|---|
레퍼런스] 엘라스틱서치란 무엇인가? (0) | 2021.09.15 |
6. 데이터 색인과 텍스트 분석 (0) | 2021.09.06 |
5. 검색과 쿼리 (0) | 2021.09.05 |
4. 데이터 처리 (0) | 2021.08.31 |