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

 

Reindex API | Elasticsearch Guide [7.15] | Elastic

Deprecated in 7.6. Sort in reindex is deprecated. Sorting in reindex was never guaranteed to index documents in order and prevents further development of reindex such as resilience and performance improvements. If used in combination with max_docs, conside

www.elastic.co

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-document-reindex.html

 

Reindex API | Java REST Client [7.15] | Elastic

Asynchronous executionedit Executing a ReindexRequest can also be done in an asynchronous fashion so that the client can return directly. Users need to specify how the response or potential failures will be handled by passing the request and a listener to

www.elastic.co

 

사전이 변경되었거나, 기존 분석기, 토크나이저, 토큰필터가 변경되었다면 인덱스를 다시 생성해줘야합니다

인덱스를 새로 생성한 후, 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

 

[Elasticsearch] IndexTemplate (인덱스템플릿)

안녕하세요~ 잭코딩입니다! 오늘은 실무에서 잘 활용하고 있는 Elasticsearch의 IndexTemplate 기능을 포스팅해보려고 합니다 https://www.elastic.co/guide/en/elasticsearch/reference/current/index-templates..

jackjeong.tistory.com

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);
	}