Search code examples
javaspring-bootelasticsearchspring-data-elasticsearch

How to search Startswith and Endswith in Elasticsearch using Java?


I am using Spring-Data-Elasticsearch and I have the following queries,

findByStatusIdAndLinkStartingWith(String statusId, String link);
findByStatusIdAndLinkEndingWith(String statusId, String link);

And it works fine. But I need to know how to implement this in CriteriaQuery or with NativeSearchQueryBuilder? And also I have seen that StartingWith is possible with Prefix Query but says it will slow. So what is underlying query used in findByStatusIdAndLinkStartingWith by spring-data-elasticsearch? What is the correct and best way to implement the above in single query like CriteriaQuery or with NativeSearchQueryBuilder?


Solution

  • Spring Data Elasticsearch internally builds a CriteriaQuery for a repository method that has StartingWith in in it's name:

    https://github.com/spring-projects/spring-data-elasticsearch/blob/main/src/main/java/org/springframework/data/elasticsearch/repository/query/parser/ElasticsearchQueryCreator.java#L113-L116:

    case STARTING_WITH:
      return criteria.startsWith(parameters.next().toString());
    case ENDING_WITH:
      return criteria.endsWith(parameters.next().toString());
    

    This CriteriaQuery is then processed to an Elasticsearch QueryBuilder (https://github.com/spring-projects/spring-data-elasticsearch/blob/main/src/main/java/org/springframework/data/elasticsearch/core/CriteriaQueryProcessor.java#L205-L210):

    case STARTS_WITH:
        query = queryStringQuery(searchText + '*').field(fieldName).analyzeWildcard(true);
        break;
    case ENDS_WITH:
        query = queryStringQuery('*' + searchText).field(fieldName).analyzeWildcard(true);
        break;
    

    which then will be given to the RestHighLevelClient.

    So if you use a CriteriaQuery this will end in the same query being sent to Elasticsearch. If you have a different performant query, then you'll need to use a NativeSearchQuery to create that.