Spring Data Elasticsearch: множественный индекс с одним и тем же документом

Я использую spring -data-elasticsearch, и для начала все работает нормально.

@Document( type = "products", indexName = "empty" )
public class Product
{
...
}

public interface ProductRepository extends ElasticsearchRepository<Product, String>
{
...
}

В моей модели я могу искать продукты.

@Autowired
private ProductRepository repository;
...
repository.findByIdentifier( "xxx" ).getCategory() );

Итак, моя проблема: у меня такой же тип Elasticsearch в разных индексах, и я хочу использовать один и тот же документ для всех запросов. Я могу обрабатывать больше соединений через пул, но я не знаю, как это реализовать.

Я хотел бы иметь что-то вроде этого:

ProductRepository customerRepo = ElasticsearchPool.getRepoByCustomer("abc", ProductRepository.class);
repository.findByIdentifier( "xxx" ).getCategory();

Можно ли создать репозиторий во время выполнения с другим индексом?

Большое спасибо Марсель

Ответ 1

Да. Это возможно с помощью Spring. Но вы должны использовать ElasticsearchTemplate вместо Repository.

Например. У меня есть два продукта. Они хранятся в разных индексах.

@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

}

Предположим, что они имеют один и тот же тип, поэтому они имеют одинаковые поля. Но это не нужно. Два продукта могут иметь совершенно разные поля.

У меня есть два репозитория:

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


public interface ProductBRepository
    extends ElasticsearchRepository<ProductB, String> {


}

Это тоже не нужно. Только для тестирования. Тот факт, что ProductA хранится в индексе "product-a" и ProductB, хранится в индексе "product-b".

Как запросить два (десять, десяток) индексов одного типа?

Просто создайте пользовательский репозиторий, подобный этому

@Repository
public 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;
        });
    }

}

Вы можете искать столько индексов, сколько хотите, и вы можете прозрачно вводить это поведение в ProductARepository добавление пользовательского поведения в отдельные хранилища

Второе решение - использовать псевдонимы индексов, но вам также нужно было создать собственную модель или пользовательский репозиторий.