- Elasticsearch에 많이 사용되는 필드 데이터 타입들을 이해한다. (8.x 버전 기준)
text#
- 문자열 전체를 애널라이저로 분석하여 색인화하는 필드
- 전체 텍스트 내에서 일부 단어로 검색할 수 있다.
- 집계나 정렬에서는 사용할 수 없다.
- 만약 텍스트 전문 검색과 집계/정렬이 모두 필요한 상황이라면 다중 필드를 사용해서 keyword와 text를 동시에 사용할 수 있다.
PUT my-index-000001
{
"mappings": {
"properties": {
"city": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
}
파라미터#
"analyzer": "<애널라이저명>": 텍스트 필드에 사용할 애널라이저"search_analyzer": "<애널라이저명>": 검색을 할 때 기본적으로 analyzer 파라미터와 동일한 애널라이저로 사용한다. 해당 파라미터로 검색시에 사용할 애널라이저를 변경할 수 있다."index": <true | false>: false로 설정하면 해당 필드를 색인화하지 않는다 (기본값: true)"boost": <숫자 값>: 풀텍스트 검색 시 필드 스코어 점수의 가중치 (기본값: 1)"fielddata": <true | false>: 정렬, 집계를 위해 해당 필드를 메모리로 로드해 사용한다는 설정. true로 설정하면 메모리 사용량이 많아지기 때문에 일반적으로 권장하지 않는 옵션 (기본값: false)
keyword#
- 정렬, 집계, term(정확히 일치) 검색 같은 목적으로 사용할 수 있는 타입
- 숫자 형식의 데이터라도 아래의 상황이면 keyword로 매핑하는 것이 유리하다.
- 범위 검색을 할 상황이 없는 경우
- 빠른 검색이 중요한 경우.
keyword 타입이 숫자 타입보다 term 쿼리 속도가 더 빠른 경우가 잦다.
파라미터#
index, boost: text 필드와 동일하게 동작"doc_values": <true | false>: true로 설정하면 집계나 정렬에 메모리를 사용하지 않기 위해 별도의 열 기반 저장소에 저장한다. false로 하면 집계나 정렬이 불가능해진다. (기본값: true)"ignore_above": <자연수>: 설정된 길이 이상의 문자열은 색인을 하지 않아 검색이나 집계가 불가능하다. (기본값: 2,147,483,647, 다이나믹 매핑으로 생성할 경우: 256)
constant_keyword#
- 모든 도큐먼트에 동일한 값이 저장되어야 하는 경우에 사용할 수 있는 특별한 keyword 타입
PUT logs-debug
{
"mappings": {
"properties": {
"@timestamp": {
"type": "date"
},
"message": {
"type": "text"
},
"level": {
"type": "constant_keyword",
"value": "debug"
}
}
}
}
- 도큐먼트에 저장된 값이 모두 값다는 특성을 활용해서 쿼리가 보다 효율적으로 실행된다.
POST logs-debug/_doc
{
"@timestamp": "2019-12-12",
"message": "Starting up Elasticsearch",
"level": "debug"
}
POST logs-debug/_doc
{
"@timestamp": "2019-12-12",
"message": "Starting up Elasticsearch"
}
wildcard#
*abc* 같은 와일드카드 검색이나 정규식 검색을 효율적으로 하기 위한 특별한 keyword 타입- 기존 keyword 필드는 전체 문자열을 하나로 저장하기 때문에 와일드카드 검색이 매우 느렸다.
- wildcard 타입은 ngram을 사용해서 필드 값을 인덱싱한다.
- vs keyword
- 일반적인 keyword보다 와일드카드나 정규식으로 이용한 검색이 더 빠르다.
- 일반적인 keyword보다 정확한 일치 검색은 더 느리다.
- vs text
- 문자열 부분 검색은 wildcard가 더 빠르게 처리한다.
- wildcard는 애널라이저를 사용하지 않기 때문에 형태소 분석 같은 자연어 검색에서는 사용 불가능하다.
PUT my-index-000001
{
"mappings": {
"properties": {
"my_wildcard": {
"type": "wildcard"
}
}
}
}
PUT my-index-000001/_doc/1
{
"my_wildcard" : "This string can be quite lengthy"
}
GET my-index-000001/_search
{
"query": {
"wildcard": {
"my_wildcard": {
"value": "*quite*lengthy"
}
}
}
}
숫자 타입#
long, integer, short, byte, double, float, scaled_float, …- 타입 선택 기준
- 작은 타입일 수록 인덱싱과 검색 효율성이 높아지므로, 데이터를 충분히 저장할 수 있는 타입중 가장 작은 타입을 선택해야 한다.
- 부동 소수점일 경우
scaled_float를 사용해서 내부적으로 정수로 저장하는 것이 더 효율적일 수 있다.scaled_float는 scaling_factor라는 파라미터를 제공한다.scaling_factor를 100으로 설정하고 필드에 12.345를 저장시도하면 내부적으로는 이를 100배 해서 정수로 저장하여, 12.34 가 저장된다.
파라미터#
index, doc_values, boost: text, keyword 필드 옵션과 같다."coerce": <true | false>: 숫자로 이해될 수 있는 값들을 자동으로 숫자로 변경해서 저장할 지 여부 (기본값: true)- 예시: integer 필드에
"4", 4.5 를 입력하면 자동으로 4로 변환해서 저장
"null_value": <숫자값>: 필드값이 입려되지 않았거나 null인 경우 디폴트 값을 지정한다.
date#
- JSON 에는 date 타입이 때문에 아래의 형식이면 date 타입으로 인식한다.
- 날짜 포맷의 string
milliseconds-since-the-epoch의 정수seconds-since-the-epoch 의 정수
파라미터#
doc_values, index, null_value 옵션은 text, keyword, 숫자 타입과 동일"format": "<문자열 || 문자열 ...>": 입력 가능한 날짜 형식을 || 로 구분해서 입력
boolean#
doc_values, index, null_value 옵션은 text, keyword, 숫자 타입과 동일
object#
- 하나의 필드에 계층적으로 내부로 필드를 만들 경우에 사용 가능하다.
- 아래 예시와 같이
properties를 입력하고 그 아래에 하위 필드의 이름과 타입을 지정하면 된다.
PUT my-index-000001
{
"mappings": {
"properties": {
"region": {
"type": "keyword"
},
"manager": {
"properties": {
"age": { "type": "integer" },
"name": {
"properties": {
"first": { "type": "text" },
"last": { "type": "text" }
}
}
}
}
}
}
}
nested#
- object 배열을 각각 독립적으로 검색할 수 있는 방식으로 인덱싱을 해주는 특별한 object 타입
- object 타입의 배열은 내부적으로 평탄화 시켜서 저장이 된다.
- 아래와 같이 도큐먼트를 저장하면 내부적으로는 object 끼리 묶여서 인덱싱이되지 않고 하나로 평탄화되어서 인덱싱된다.
- 따라서 first가 “Alice"이고 last가 “Smith"인 도큐먼드만 검색할 수 있는 방법이 없다.
PUT my-index-000001/_doc/1
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
{
"group" : "fans",
"user.first" : [ "alice", "john" ],
"user.last" : [ "smith", "white" ]
}
- nested 타입은 배열 내의 각 object들을 별도의 숨겨진 문서로 인덱싱 하기 때문에 독립적으로 쿼리할 수 있다.
GET my-index-000001/_search
{
"query": {
"nested": {
"path": "user",
"query": {
"bool": {
"must": [
{ "match": { "user.first": "Alice" }},
{ "match": { "user.last": "Smith" }}
]
}
}
}
}
}
참고 자료#