Search code examples
elasticsearchspring-dataspring-data-elasticsearch

Spring Data Elastic Search with dynamic document replicas and shards


I'm using spring boot 2.4 and spring-data-elasticsearch 4.1. I have document like this

@Document(indexName = "test", replicas = 3, shards = 2)
public class TestDocument {
  @Id
  @Field(type = FieldType.Keyword)
  private String Id;

  @Field(type = FieldType.Object, enabled = false)
  private String name;
  ...
  getters
  setters
}

And i want to override hardcoded values in replicas and shards in Document annotation from application.yml for index creation because this values can be differnet by environment of my service. Is there any way to do this?


Solution

  • You can disable auto-creation of an index by using

    @Document(indexName = "test", createIndex = false)
    

    and then create the index by using the IndexOperations.create(settings). The following code is taken from Spring Data Elasticsearch tests (https://github.com/spring-projects/spring-data-elasticsearch/blob/4.1.x/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java#L2361-L2384):

        public void shouldCreateIndexWithGivenClassAndSettings() {
    
            // given
            String settings = "{\n" + "        \"index\": {\n" + "            \"number_of_shards\": \"1\",\n"
                    + "            \"number_of_replicas\": \"0\",\n" + "            \"analysis\": {\n"
                    + "                \"analyzer\": {\n" + "                    \"emailAnalyzer\": {\n"
                    + "                        \"type\": \"custom\",\n"
                    + "                        \"tokenizer\": \"uax_url_email\"\n" + "                    }\n"
                    + "                }\n" + "            }\n" + "        }\n" + '}';
    
            // when
            indexOperations.delete();
            indexOperations.create(parse(settings));
            indexOperations.putMapping(SampleEntity.class);
            indexOperations.refresh();
    
            // then
            Map<String, Object> map = indexOperations.getSettings();
            assertThat(operations.indexOps(IndexCoordinates.of(INDEX_NAME_SAMPLE_ENTITY)).exists()).isTrue();
            assertThat(map.containsKey("index.number_of_replicas")).isTrue();
            assertThat(map.containsKey("index.number_of_shards")).isTrue();
            assertThat((String) map.get("index.number_of_replicas")).isEqualTo("0");
            assertThat((String) map.get("index.number_of_shards")).isEqualTo("1");
        }
    

    Instead of parsing the JSON for the settings you should create a Document in your code:

    Document settings = Document.create();
    settings.put("index.number_of_replicas", 42);
    settings.put("index.number_of_shards", 42);