Elasticsearch (ELK)/Elasticsearch

8-2. Settings & Mappings - Mappings

Velody 2020. 5. 29. 10:46

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 에서 정의하며 토크나이저는 적용할 수 없고 캐릭터 필터와 토큰 필터만 적용해서 사용이 가능합니다.

 

  • 숫자
    • 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 : 도큐먼트 범위 값과 쿼리 범위에 공통적인 부분이 있는 도큐먼트들을 가져옵니다.

 

 

 

 

 

예제 

 

// 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
      }
    }
  }
}