Spring Data Elasticsearch:具有相同文档的多个索引 [英] Spring Data Elasticsearch: Multiple Index with same Document

查看:1430
本文介绍了Spring Data Elasticsearch:具有相同文档的多个索引的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  @Document(type =产品,indexName =empty)
public class Product
{
...
}

public interface ProductRepository扩展ElasticsearchRepository< Product,String> ;
{
...
}

在我的模型中可以搜索产品。

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

所以,我的问题是 - 我在不同的索引中有相同的弹性搜索类型,我想使用所有查询的相同文档。我可以通过一个池来处理更多的连接 - 但是我不知道我该如何实现这个。



我想拥有这样的东西: p>

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

可以在运行时创建一个不同索引的存储库吗?



非常感谢
Marcel

解决方案

是的。有可能与春天。但是您应该使用 ElasticsearchTemplate ,而不是 Repository



例如。我有两个产品。它们存储在不同的索引中。

  @Document(indexName =product-a,type =product)
public class ProductA {

@Id
private String id;

private String name;

private int value;

// Getters和setter
}

@Document(indexName =product-b,type =product)
public class ProductB {

@Id
private String id;

private String name;

// Getters和setters

}





我有两个存储库:

  public interface ProductARepository扩展了ElasticsearchRepository< ProductA,String> {
}


public interface ProductBRepository
扩展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);

//您可以根据需要查询任意数量的索引
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();
列表< ProductA> result = new ArrayList& ;
Arrays.stream(hits.getHits())。forEach(h - > {
Map< String,Object> source = h.getSource();
//仅获取id只是为了测试
ProductA productA = new ProductA()
.setId(String.valueOf(source.getOrDefault(id,null)));
result.add(productA);
});
return result;
});
}

}

您可以搜索尽可能多的索引你想要的,你可以透明地将这个行为注入 ProductARepository 将自定义行为添加到单个存储库



第二个解决方案是使用索引别名,但您必须创建自定义模型或自定义存储库。


I'm using spring-data-elasticsearch and for the beginning everything works fine.

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

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

In my model i can search for products.

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

So, my problem is - I've the same Elasticsearch type in different indices and I want to use the same document for all queries. I can handle more connections via a pool - but I don't have any idea how I can implement this.

I would like to have, something like that:

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

Is it possible to create a repository at runtime, with an different index ?

Thanks a lot Marcel

解决方案

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

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

}

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.

这篇关于Spring Data Elasticsearch:具有相同文档的多个索引的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆