Elasticsearch 매핑 관리 + 템플릿

매핑 관리 + 템플릿

매핑(Mapping)은 앞에서 설명한 대로 필드의 Key의 형태를 정의한 것이다. 한번 작성한 매핑은 필드 추가를 제외하고 수정할 수 없다. 수정하려면 인덱스를 다시 만들어야 한다.

매핑을 생성 및 추가하는 아래 4가지 방법이 있다.

  • 자동으로 매핑 만들기
  • 수동으로 매핑 만들기
  • 템플릿으로 매핑 만들기
  • 기존 매핑에 필드 추가

자동으로 매핑 만들기

Elasticsearch는 다음과 같이 인덱스에 도큐먼트를 생성할 때에 자동으로 매핑을 생성한다.

mapping_test 인덱스에 도큐먼트를 생성

PUT /mapping_test/_doc/1
{
  "date":"2021/12/01 09:00:00+0900",
  "Tweet":"This is a mapping test."
}

매핑 확인

GET /mapping_test

맵핑 내용

GET /mapping_test
{
  "mapping_test" : {
    "aliases" : { },
    "mappings" : {
      "properties" : {
        "Tweet" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "date" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    },

// ... 이하 생략 ...

위의 결과 내용을 보면 다음과 같은 매핑이 정의되었음을 알 수 있다. text 형과 keyword 형의 차이에 대해서는 설명은 아래와 같다.

  • date, Tweet 키는 text 타입
  • date.keyword, text.keyword 키는 keyword 타입

위에서 작성한 매핑의 date 키는 text 형으로 등록되어 있지만, date 타입으로 등록해야 하는 경우가 있다. 그런 경우 수동으로 매핑을 만들어야 한다.

수동으로 매핑 만들기

수동으로 매핑을 만드는 방법은 다음과 같다.

수동 매핍을 생성

PUT /mapping_test2
{
  "mappings": {
    "properties": {
      "date":    { 
        "type": "date",
        "format": "yyyy/MM/dd HH:mm:ssZ"
      },  
      "tweet":  {
        "type": "text",
        "fields": {
          "keyword":{
            "type":"keyword"
          }
        }
      }
    }
  }
}

수동으로 매핑을 생성한 결과

GET /mapping_test2

수동으로 생성한 매핑 내용

GET /mapping_test2
{
  "mapping_test2" : {
    "aliases" : { },
    "mappings" : {
      "properties" : {
        "date" : {
          "type" : "date",
          "format" : "yyyy/MM/dd HH:mm:ssZ"
        },
        "tweet" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword"
            }
          }
        }
      }
    },

... 이하 생략 ...

제대로 생성이 되었다면 date 키가 date 타입으로 매핑되고 있는 것을 알 수 있다.

매핑에 지정된 포멧과 다른 경우

매핑에 지정된 형식과 다른 도큐먼트를 만들면 오류가 발생한다.

실행해 보면 date 필드의 포맷은 "yyyy/MM/dd HH:mm:ssZ" 이지만, 다른 포맷으로 "yyyy/MM/dd HH:mm:Z"(초를 지정하지 않았다) 데이터를 넣어본다.

매핑이 지정한 포멧과 다른 도큐먼트를 생성

PUT /mapping_test2/_doc/1
{
  "date":"2021/12/01 09:00+0900",
  "tweet":"This is a mapping test."
}

에러 메세지

{
  "error" : {
    "root_cause" : [
      {
        "type" : "mapper_parsing_exception",
        "reason" : "failed to parse field [date] of type [date] in document with id '1'. Preview of field's value: '2021/12/01 09:00+0900'"
      }
    ],

... 이하 생략 ...

예상한 대로 date 필드를 구문 분석 할 수 없다. 메세지가 나온다.

매핑에서 지정한 포멧과 같은 경우

이제 올바른 포멧으로 도큐먼트를 작성해 본다.

매핑에 포멧대로 도큐먼트를 생성

PUT /mapping_test2/_doc/2
{
  "date":"2020/11/01 09:00:00+0900",
  "tweet":"This is a mapping test."
}

올바른 포멧으로 도큐먼트를 생성하면 성공하는 것을 볼 수 있다.

템플릿으로 매핑 만들기

인덱스마다 동일한 매핑을 여러번 만드는 것은 어렵다. 이를 해결하는 것이 템플릿이다.

템플릿은 지정한 이름의 인덱스가 작성되었을 때, 템플릿의 매핑을 이용해 인덱스를 작성한다. 템플릿을 만들려면 template API를 사용한다.

_template API를 사용한다.

PUT /_template/test_template
{
  "index_patterns": "test*",
  "mappings": {
    "properties": {
      "date":    { 
        "type": "date",
        "format": "yyyy/MM/dd HH:mm:ssZ"
      },  
      "tweet":  {
        "type": "text",
        "fields": {
          "keyword":{
            "type":"keyword"
          }
        }
      }
    }
  }
}

위에 템플릿에서는, "index_patterns": "test*" 로 지정했듯이, 인덱스명의 접두사에 "test" 가 있는 경우, 지정한 매핑을 생성한다.

템플릿의 동작을 확인해 보자.

test 인덱스를 생성

PUT /test

test 인덱스의 매핑 확인

GET /test

test 인덱스의 매핑 결과 확인

GET /test
{
  "test" : {
    "aliases" : { },
    "mappings" : {
      "properties" : {
        "date" : {
          "type" : "date",
          "format" : "yyyy/MM/dd HH:mm:ssZ" // 템플릿에 지정된 format으로 date 필드가 등록
        },
        "tweet" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword"
            }
          }
        }
      }
    },

... 이하 생략 ...

템플릿에 지정된 format으로 date 필드가 등록된 것을 알 수 있다.

기존 매핑에 필드 추가

기존 매핑에 새 필드를 추가하려면 mapping API를 사용한다.

additional_field 필드를 mapping_test2 인덱스 매핑에 추가해 보겠다.

mapping_test2의 내용

GET /mapping_test2
{
  "mapping_test2" : {
    "aliases" : { },
    "mappings" : {
      "properties" : {
        "date" : {
          "type" : "date",
          "format" : "yyyy/MM/dd HH:mm:ssZ"
        },
        "tweet" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword"
            }
          }
        }
      }
    },
... 이하 생략 ...

매핑에 포멧을 추가

PUT /mapping_test2/_mapping
{
  "properties":{
    "additional_field":{
      "type":"text"
    }
  }
}

additioinal_field 포멧이 추가된거 확인

GET /mapping_test2

additioinal_field 포멧이 추가된거 결과 확인

{
  "mapping_test2" : {
    "aliases" : { },
    "mappings" : {
      "properties" : {
        "additional_field" : { // additional_field 필드가 추가되었음
          "type" : "text"
        },
        "date" : {
          "type" : "date",
          "format" : "yyyy/MM/dd HH:mm:ssZ"
        },
        "tweet" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword"
            }
          }
        }
      }
    },
... 이하 생략 ...

additional_field 필드가 추가되었음을 확인하였다.