Search code examples
javaelasticsearchspring-data-elasticsearch

Elasticsearch QueryBuilder: find by ids and prefix


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?


Solution

  • 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.