1 minute read

회사서 얼마전 승우님 인덱스에 값을 잘못 넣었어요, 이걸 어떻게 수정하나요? 질문을 듣고 당황하였다.

그 docs를 변경하는건 어렵지 않지만 mapping정보를 바로 변경하는건 없는걸로 알았기 때문이다.

그래서 reindex를 하는 방법을 알려드렸고,

ElasticDump 사용법 또한 알려드렸다.

이번 포스팅에서도 적잖이 당황할 유저들을 위해 이 글을 남긴다.

기본적인 reindex 방법

  1. TEST 인덱스를 생성한다.
    PUT test_reindex
    {
      "mappings": {
         "properties": {
             "id": {
                 "type": "integer"
             },
             "name": {
                 "type": "text",
                 "fields": {
                     "keyword": {
                         "type": "keyword"
                     }
                 }
             }
         }
     }
    }
    

    실수를 하기 위해 dynamic 옵션은 켜두도록하자

POST test_reindex/_doc/1
{
  "id": 1,
  "name": "test",
  "test": "test"
}

POST test_reindex/_doc/2
{
  "id": 2,
  "test": "test"
}

id 2 번에 기존에 우리가 지정하지 않은 test라는 field를 생성하였다.

GET test_reindex/_mapping

결과 제길.. test filed가 생성되었다

{
  "test_reindex" : {
    "mappings" : {
      "properties" : {
        "id" : {
          "type" : "integer"
        },
        "name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword"
            }
          }
        },
        "test" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

이제 이걸 어떻게 해결해야 할까?.. 옮길 인덱스를 만들고

PUT test_reindex_temp
{
  "mappings": {
        "properties": {
            "id": {
                "type": "integer"
            },
            "name": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword"
                    }
                }
            }
        }
    }
}

reindex를 하면 mapping 정보들은 모두 변경이 될것이다.

POST _reindex
{
    "source": {
        "index": "test_reindex"
    },
    "dest": {
        "index": "test_reindex_temp",
    }
}

좋아좋아. 그런데,,, _doc id:3 은 여전이 test라는 필드를 가지고 있다.

만약 id를 알고 있다면 올바른 값으로 덮어 씌우면 되지만

만약 id도 모르고, bulk로 작업을 하여서 다시 돌리는것이 힘들다면 낭패일것이다..

하지만 이것도 다 방법이 있다. 방법은 아래와 같다.

먼저 파이프라인을 하나 만들어 준다.

PUT _ingest/pipeline/my_pipeline
{
  "description": "Removes the 'foo' field", 
  "processors": [
    {
      "remove": {
        "field": "test",
        "ignore_missing": true
      }
    }
  ]
}

그후 reindex를 할때 이전 처럼 하는것이 아니고. 파이프 라인을 추가하여 reindexing를 한다.

POST _reindex
{
    "source": {
        "index": "test_reindex"
    },
    "dest": {
        "index": "test_reindex_temp",
        "pipeline": "my_pipeline"
    }
}

이러면 test filed도 사라지고 reindex도 정상적으로 완료!!!

그런데 데이터가 많은 운영환경 경우, reindex는 굉장히 작업비용이 크기 떄문에 애초에 mapping 을 dynamic false로 하고 처음부터 잘 설계하는게 중요할것 같다.

이후에는 기존의 인덱스를 삭제하고 아래와 같이 사용하고자 하는 index 네임으로 alias 를 하여 다시 사용하면 된다.

PUT /{old_index_name}/_settings
{
    "index.analysis.analyzer.default.type": "standard",
    "index.number_of_shards": 1,
    "index.number_of_replicas": 1
}
POST /_aliases
{
    "actions": [
        {
            "add": {
                "index": "{old_index_name}",
                "alias": "{test_reindex}"
            }
        }
    ]
}