Elastic

Elasticsearch reindex - 재색인

탱자x2 2021. 9. 17. 13:58

아직 생성되지 않은 인덱스에 매핑을 추가하고 도큐먼트를 추가하기도 해 봤고, author 필드가 없어서 필드를 추가하기도 해 봤어요.

그러면 기존의 필드 매핑 타입을 변경하는 건 어떻게 할까요? 결론부터 말하자면 안돼요. 필드에 "ignore_above"와 같이 몇몇 매핑 파라미터를 추가하거나 변경하는 건 가능하지만 대부분의 경우엔 매핑 타입을 변경할 수 없어요.

그럼 왜 기존 인덱스의 매핑 정보를 수정하는 게 안 되는 걸까요? 여러 가지 이유가 있겠지만 중요한 이유 중 하나는 매핑 정보가 변경되면 데이터가 저장되는 방식이 바뀌게 돼요. text형으로 인덱싱이 완료된 필드를 keyword타입으로 변경하면 어떻게 될지 생각해보세요.

 

인덱스에 매핑을 생성했는데 아직 도큐먼트를 추가하지는 않았어도 안돼요. 변경할 수 없어요. 아. 삭제도 안 돼요.

 

그럼 어떻게 해야 할까요?

 

reindex

새로운 인덱스를 생성하고 변경된 타입으로 매핑을 만들고 기존 인덱스의 도큐먼트들을 새로 생성한 인덱스로 넣어주는 걸 스크립트로 작성할 수 있을 것 같아요. 그런데 그럴 필요 없이 이미 엘라스틱서치는 그렇게 동작하는 reindex라는 API를 만들어 놨어요.

 

그럼 그 과정을 한 번 볼까요?

 

먼저 기존 books 인덱스를 지워줄게요.

DELETE /books

그리고 새로 만들어줄게요.

POST /books/_doc/HarryPotterBook1
{
  "title": "Harry Potter and the Sorcerer's Stone",
  "rating": 4.8,
  "in_stock": 739,
  "price": 21.99
}

어머. 책 소개를 넣는 걸 깜빡했어요. 아래 요청으로 보내서 책 소개를 넣어볼까요?

POST /books/_update/HarryPotterBook1
{
  “doc”: {
    “desc”: “””Turning the envelope over, his hand trembling, Harry saw a purple wax seal bearing a coat of arms; a lion, an eagle, a badger and a snake surrounding a large letter 'H'.
Harry Potter has never even heard of Hogwarts when the letters start dropping on the doormat at number four, Privet Drive. Addressed in green ink on yellowish parchment with a purple seal, they are swiftly confiscated by his grisly aunt and uncle. Then, on Harry's eleventh birthday, a great beetle-eyed giant of a man called Rubeus Hagrid bursts in with some astonishing news: Harry Potter is a wizard, and he has a place at Hogwarts School of Witchcraft and Wizardry. An incredible adventure is about to begin!
Having now become classics of our time, the Harry Potter ebooks never fail to bring comfort and escapism to readers of all ages. With its message of hope, belonging and the enduring power of truth and love, the story of the Boy Who Lived continues to delight generations of new readers.”””
  }
}

"""이렇게

묶으면

띄어쓰기도 넣을 수 있더라고요"""

 

그리고 매핑을 확인해봤더니 어머나

...
"desc" : {
  "type" : "text",
    "fields" : {
      "keyword" : {
      	"type" : "keyword",
      	"ignore_above" : 256
      }
    }
  },
...

description 필드가 text형인 것 까지는 좋은데 저 keyword타입은 필요 없을 것 같으니 빼고 싶어요. 그런데 매핑 정보를 수정할 수는 없으니 기존 인덱스의 매핑 정보를 확인하고 새로 인덱스를 만들어서 매핑 정보를 먼저 넣어주고 그 새로운 인덱스로 리인덱스 해볼게요.

 

books/_mappings 정보를 확인하고 복사해 놓을게요. 그리고 새로 인덱스를 만들어주세요

PUT /books_new
{
  "mappings": {
    "properties": {
      ...
      "desc": {
        "type": "text"
      }
      ...
    }
  }
}

이렇게 desc 필드는 확실하게 text 타입으로 만들었어요.

 

자 준비는 이제 끝났고 이제 reindex를 실행해볼게요

POST /_reindex
{
  "source": {"index": "books"},
  "dest": {"index": "books_new"}
}

짠. 끝났어요. 도큐먼트가 하나만 있어서 정말 눈 깜짝할 틈도 없이 완료가 됐어요. 확실한 건 새로 스크립트를 만든다거나 뭐 그런 수고는 필요 없다는 거예요.

 

reindex에는 다른 더 많은 더 다양한 기능들이 있는데 이 거 하나만 더 보고 오늘은 끝내려고 해요.

 

지금 books_new 인덱스에는 title, rating, in_stock, price, desc 이렇게 5개의 필드가 있는데요 books에서 title, rating, price, desc 이렇게 4개 필드만 새로 생성한 인덱스로 넘기고싶었다면 아래와 같이 하는 방법이 있어요.

POST /_reindex
{
  "source": {"index": "books", "_source": ["title", "price", "rating", "desc"]},
  "dest": {"index": "books_new"}
}

그리고 오브젝트형에서 이번엔 안 만들었지만 지난번과 같이 author에 first_name, last_name과 같은 필드가 있었다고 가정했을 때 last_name만 새로운 인덱스로 넘기고 싶다 했으면 "_source": ["title", "price", "rating", "desc", "author.last_name"]

이렇게도 사용 할 수 있어요. 예전에 그 .(dot) notation을 활용해서요.

 

자, 그럼 새로 만들어진 인덱스와 도큐먼트 매핑 등을 확인해보세요.

 

 

그럼 reindex는 여기까지 할게요.