Home > Blockchain >  Elasticsearch QueryBuilder: find by ids and prefix
Elasticsearch QueryBuilder: find by ids and prefix

Time:06-24

I'm implementing custom repository based on Spring Data Elasticsearch:

@Document(indexName = "product", createIndex = false)
public class ProductDocument implements Serializable {

    @Id
    private String id;

    @NotNull
    private String name;
}

@Override
public List<ProductDocument> findByIdsAndName(List<String> productIds, String name) {
    Query query = new NativeSearchQueryBuilder()
            .withIds(productIds)
            .withQuery(QueryBuilders.prefixQuery("name", name))
            .build();

    return operations.search(query, clazz, indexCoordinates)
            .stream()
            .map(SearchHit::getContent)
            .collect(Collectors.toList());
}

The problem I'm facing is that the query is not working, e.g. I save into ES items like

productRepository.saveAll(Arrays.asList(
                ProductDocument.builder().id("1").name("Pikachu1").build(),
                ProductDocument.builder().id("2").name("Pikachu2").build(),
                ProductDocument.builder().id("3").name("Pikachu3").build(),
                ProductDocument.builder().id("4").name("Pikachu4").build(),
                ProductDocument.builder().id("5").name("Pikachu5").build()
        )

and then call the method

assertThat(productRepository.findByIdsAndName(List.of("1", "2"), "Pika")).hasSize(2);

repository method returns an empty list and assertion fails. I've also tried to implement query like

Query query = new NativeSearchQueryBuilder()
        .withFilter(QueryBuilders.idsQuery().addIds(productIds.toArray(String[]::new)))
        .withQuery(QueryBuilders.prefixQuery("name", name))
        .build();

but it fails either. The problem seems to be about prefixQuery because when I remove it the query works.

What am I doing wrong?

CodePudding user response:

Are you sure the id is the _id elasticsearch also searches for. It could be that it is a property of the document but the actual id is something else. I had this issue. So I stored a document with an id attribute but elasticsearch assigned an id itself which had nothing to do with the id of the document. Maybe try with postman or a restcall to check what exactly is inside elasticsearch after saveAll.

CodePudding user response:

I've found a work-around:

@Override
public List<ProductDocument> findByIdsAndName(Collection<String> productIds, String name) {
    BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
    queryBuilder.must(QueryBuilders.idsQuery().addIds(productIds.toArray(String[]::new)));
    queryBuilder.must(QueryBuilders.matchBoolPrefixQuery("name", name));

    Query query = new NativeSearchQueryBuilder().withQuery(queryBuilder).build();

    return operations.search(query, clazz, indexCoordinates)
            .stream()
            .map(SearchHit::getContent)
            .collect(Collectors.toList());
}

Still I think that this is a bug. I've filed an issue here: https://github.com/spring-projects/spring-data-elasticsearch/issues/2188

Let's wait for maintainer's response.

  • Related