ElasticSearch

[ElasticSearch] dynamic strict 옵션

SongMinu 2022. 5. 15. 20:51
728x90

https://minu0807.tistory.com/106

 

[ElasticSearch]index 생성시 DynamicTemplate 사용

일반적으로 인덱스를 생성할 때 맵핑 정보를 지정하고 사용하다 보면, 불편한 점이 있다. 이런 식으로 인덱스가 생성되었다고 할 때, 저기에 입력된 4개의 맵핑 정보를 제외하고 실수로 다른 정

minu0807.tistory.com

이 글에서 잠깐 언급했던 옵션이다.

인덱스를 만들면서 맵핑 정보를 지정할 때 저 옵션을 넣고, 인덱스를 생성한 다음에 데이터를 넣을 때, 없는 맵핑 정보가 포함된 데이터가 들어오면 에러가 발생한다.

displayName: 'BadRequest',
  path: '/user_test2/_doc',
  query: {},
  body: {
    error: {
      root_cause: [Array],
      type: 'strict_dynamic_mapping_exception',
      reason: 'mapping set to strict, dynamic introduction of [user_addr] within [_doc] is not allowed'
    },
    status: 400
  },
  statusCode: 400,
  response: '{"error":{"root_cause":[{"type":"strict_dynamic_mapping_exception","reason":"mapping set to strict, dynamic introduction of [user_addr] within [_doc] is not allowed"}],"type":"strict_dynamic_mapping_exception","reason":"mapping set to strict, dynamic introduction of [user_addr] within [_doc] is not allowed"},"status":400}',
등록되지 않은 user_addr 데이터가 들어와서 발생한 에러 로그.

 

해당 옵션은 주는게 좋다고 개인적으로 생각한다.

설계를 너무 완벽하게 해서 추후에 필드 추가를 할 일이 없다면 상관없겠지만 아닐 때가 더 많기 때문에 방지용으로 넣는 게 좋다 생각한다.

혹은 적절하게 dynamicTemplates를 써서 방지할 수 있겠지만 그러면 실수로 추가된 필드가 의도치 않게 들어가서 불필요한 맵핑 정보가 생길 수도 있다.

 

가장 문제가 되는 상황

엘라스틱서치의 특성상 한 번 만들어진 필드는 수정이나 삭제가 안된다.

변경하기 위해선 리인덱스를 하거나, 다시 만들어야 한다.

데이터가 얼마 되지 않고 생성되는 주기가 뜸하면 그 사이를 이용해 잠시 서비스를 막고 리인덱스를 하면 되지만, 생성 주기도 짧고, 데이터도 엄청 많으면 하기도 어렵다.

데이터가 많으면 리인덱스를 하는 시간도 많이 걸리고, 데이터가 들어오고 있는 걸 막지 않는다면 리인덱스가 진행되는 동안 계속 데이터가 들어오기 때문에 문제가 된다.

실제로 실무에서 이런 문제를 몇 번 겪어 봤는데 상당히 골치가 아파진다....

그리고 실수로 가장 많이 들어가지는 경우는 보통 "오타"였다.

 

옵션을 주지 않은 예제?

아래와 같은 다이나믹템플릿을 사용하지 않은 사용자 인덱스(user_test 1)가 있고 치자.

예를 들어 위 맵핑 정보를 토대로 데이터를 사용 중에 어떤 요청사항이나 추가 개발 건으로 user_addr이라는 필드가 추가가 되어야 하는 상황이 생겼다.

그런데 실수로 user_addr이라는 맵핑 정보를 추가하지 않은 상태에서 데이터에 user_addr를 담아서 추가를 해버렸다.

그럼 이제 user_addr이 저런 형식의 필드가 생겨버린다.

물론 저렇게 만들어져도 해당 필드로 데이터 검색은 가능하긴 하다.

오래돼서 정확히 기억은 안 나는데 저런 형식으로 필드가 생성되면 안 되는 것들이 몇 가지 있던 걸로 기억한다.

먼저 문제 1개는 어그리게이션이다.

{
  "aggs": {
    "addr": {
      "terms": {
        "field": "user_addr"
      }
    }
  }
}

이런 에러가 뜬다.

{
  "aggs": {
    "addr": {
      "terms": {
        "field": "user_addr.keyword"
      }
    }
  }
}

이렇게 .keyword를 추가하면 검색되긴 한다.

하지만 정상적인 필드였으면 돼야 하는 쿼리인데 저렇게 해야 하는 것부터 불편해진다.

 

문자열을 저렇게 만들어지고, 정수는 long로 만들어진다.

2번 째 문제는 저렇게 잘못 만들어진 필드를 이제야 다시 추가를 하려고 하면 아래와 같은 에러가 발생한다.

displayName: 'BadRequest',
  path: '/user_test1/_mapping',
  query: { include_type_name: true, type: '_doc' },
  body: {
    error: {
      root_cause: [Array],
      type: 'illegal_argument_exception',
      reason: 'mapper [user_addr] cannot be changed from type [text] to [keyword]'
    },
    status: 400
  },
  statusCode: 400,
  response: '{"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"mapper [user_addr] cannot be changed from type [text] to [keyword]"}],"type":"illegal_argument_exception","reason":"mapper [user_addr] cannot be changed from type [text] to [keyword]"},"status":400}',

이미 만들어져 있기 때문에 추가를 할 수가 없다.

모든 걸 멈추고 리인덱스를 진행하거나 삭제하고 다시 만들어야 한다.

자기가 테스트 중이고 중요한 데이터도 없다면 그냥 삭제하고 다시 만드는 게 마음에 편하다.

특히 오타로 인한 잘못된 필드가 생성되는 경우를 여럿봤다. 가장 조심해야하는 것 중 하나이다.

그리고 종종 저 옵션이 있는 걸 모르고 데이터를 넣었는데 안들어가져서 당황하는 경우도 있으니 알아두는 것도 좋은 옵션이라고 생각한다.

 

반응형