Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
608 views
in Technique[技术] by (71.8m points)

java - Spring Data Elasticsearch: Multiple Index with same Document

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...