Spring Data Elasticsearch: Multiple Index with same Document Spring Data Elasticsearch: Multiple Index with same Document elasticsearch elasticsearch

Spring Data Elasticsearch: Multiple Index with same Document


Yes. It's possible with Spring. But you should use ElasticsearchTemplate instead of Repository.

For example. I have two products. They are stored in different indices.

@Document(indexName = "product-a", type = "product")public class ProductA {    @Id    private String id;    private String name;    private int value;    //Getters and setters}@Document(indexName = "product-b", type = "product")public class ProductB {    @Id    private String id;    private String name;    //Getters and setters}

Suppose if they have the same type, so they have the same fields. But it's not necessary. Two products can have totally different fields.

I have two repositories:

public interface ProductARepository extends ElasticsearchRepository<ProductA, String> {}public interface ProductBRepository    extends ElasticsearchRepository<ProductB, String> {}

It's not necessary too. Only for testing. The fact that ProductA is stored in "product-a" index and ProductB is stored in "product-b" index.

How to query two(ten, dozen) indices with the same type?

Just build custom repository like this

@Repositorypublic class CustomProductRepositoryImpl {    @Autowired    private ElasticsearchTemplate elasticsearchTemplate;    public List<ProductA> findProductByName(String name) {        MatchQueryBuilder queryBuilder = QueryBuilders.matchPhrasePrefixQuery("name", name);        //You can query as many indices as you want        IndicesQueryBuilder builder = QueryBuilders.indicesQuery(queryBuilder, "product-a", "product-b");        SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).build();        return elasticsearchTemplate.query(searchQuery, response -> {            SearchHits hits = response.getHits();            List<ProductA> result = new ArrayList<>();            Arrays.stream(hits.getHits()).forEach(h -> {                Map<String, Object> source = h.getSource();                //get only id just for test                ProductA productA = new ProductA()                        .setId(String.valueOf(source.getOrDefault("id", null)));                result.add(productA);            });            return result;        });    }}

You can search as many indices as you want and you can transparently inject this behavior into ProductARepository adding custom behavior to single repositories

Second solution is to use indices aliases, but you had to create custom model or custom repository too.


We can use the withIndices method to switch the index if needed:

NativeSearchQueryBuilder nativeSearchQueryBuilder = nativeSearchQueryBuilderConfig.getNativeSearchQueryBuilder();// Assign the index explicitly.nativeSearchQueryBuilder.withIndices("product-a");// Then add query as usual.nativeSearchQueryBuilder.withQuery(allQueries)

The @Document annotation in entity will only clarify the mapping, to query against a specific index, we still need to use above method.

@Document(indexName="product-a", type="_doc")