ELK Stack
[Elasticsearch] Reindex - (1:1, N:1, Remote Reindex)
잭피
2021. 11. 2. 17:57
안녕하세요~ 잭코딩입니다!
오늘은 Elasticsearch의 Reindex 기능을 포스팅해보려고 합니다
https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html
사전이 변경되었거나, 기존 분석기, 토크나이저, 토큰필터가 변경되었다면 인덱스를 다시 생성해줘야합니다
인덱스를 새로 생성한 후, Alias를 바꿔줄 수 있지만, reindex로 다시 생성하는 방법도 있습니다
실무를 하다보니 다른 서버에 있는 인덱스를 가져와서 작업해야하는 경우가 생겼고, Reindex 기능을 활용하였습니다
먼저 Elasticsearch에 직접 Query를 날려 Reindex하였고, 자동화를 위해 API에 해당 기능을 개발했습니다
두 가지 모두 정리해보겠습니다
아래의 내용은 모두 위의 Elasticsearch Document에 있는 내용들입니다
1. Elasticsearch
1) 같은 엘라스틱서치 서버의 인덱스를 Reindex
POST _reindex
{
"source": {
"index": "my-index-000001"
},
"dest": {
"index": "my-new-index-000001"
}
}
source에 복사할 인덱스를 설정하고, dest에 복사 결과 인덱스의 이름을 적용해줍니다
Reindex될 때, 인덱스 이름 패턴에 맞춰 인덱스템플릿이 적용됩니다
https://jackjeong.tistory.com/159
POST _reindex
{
"source": {
"index": "metricbeat-*"
},
"dest": {
"index": "metricbeat"
},
"script": {
"inline" : "ctx._source.word = ctx.source.remove(\"keyword\");"
}
}
Reindex할 때 조건을 걸거나 인덱스의 필드 이름을 변경하고 싶다면 script를 작성할 수 있습니다
예를 들어, keyword라는 필드가 있는데 word로 변경하고 싶다면
"ctx._source.word = ctx._source.remove(\"keyword\");
이렇게 script를 작성하면 됩니다
만약 2개의 index를 merge하고 싶다면,
POST _reindex
{
"source": {
"index": ["my-index-000001", "my-index-000002"]
},
"dest": {
"index": "my-new-index-000002"
}
}
이렇게 작성할 수 있습니다
2) 다른 엘라스틱서치 서버의 인덱스를 Reindex
POST _reindex
{
"source": {
"remote": {
"host": "http://otherhost:9200",
"username": "user",
"password": "pass"
},
"index": "my-index-000001"
}
},
"dest": {
"index": "my-new-index-000001"
}
}
위와 같은 형태에서 remote 필드만 추가해주면 됩니다
2. Spring & Java
위에서 작성한 쿼리를 그대로 서버쪽에 옮겨 작성한 코드입니다
1) 같은 엘라스틱서치 서버의 인덱스를 Reindex
public Map<String, Object> reindex(ReindexDto reindexDto) throws Exception {
ReindexRequest reindexRequest = new ReindexRequest();
reindexRequest.setSourceIndices(reindexDto.getSourceIndex());
reindexRequest.setDestIndex(reindexDto.getDestIndex());
reindexRequest.setRefresh(true);
return getResult(reindexRequest);
}
public Map<String, Object> reindexMerge(ReindexMergeDto reindexMergeDto) throws Exception {
ReindexRequest reindexRequest = new ReindexRequest();
reindexRequest.setSourceIndices(reindexMergeDto.getSourceIndex1(), reindexMergeDto.getSourceIndex2());
reindexRequest.setDestIndex(reindexMergeDto.getDestIndex());
reindexRequest.setRefresh(true);
return getResult(reindexRequest);
}
2) 다른 엘라스틱서치 서버의 인덱스를 Reindex
public Map<String, Object> remoteReindex(RemoteReindexDto remoteReindexDto) throws Exception {
ReindexRequest reindexRequest = new ReindexRequest();
reindexRequest.setSourceIndices(remoteReindexDto.getSourceIndex());
reindexRequest.setDestIndex(remoteReindexDto.getDestIndex());
reindexRequest.setRemoteInfo(
new RemoteInfo("http", remoteReindexDto.getRemoteHost(), remoteReindexDto.getRemotePort(), null,
new BytesArray(new MatchAllQueryBuilder().toString()),
null, null, Collections.emptyMap(),
new TimeValue(100, TimeUnit.MILLISECONDS),
new TimeValue(100, TimeUnit.SECONDS)
)
);
if (!ObjectUtils.isEmpty(remoteReindexDto.getScript())) {
reindexRequest.setScript(
new Script(
ScriptType.INLINE, "painless",
remoteReindexDto.getScript(),
Collections.emptyMap()
)
);
}
reindexRequest.setRefresh(true);
return getResult(reindexRequest);
}