6

I am using Elastic Search with Spring Data .

I have a simple method in repository:

findByUserNameContaining("a b");

This method not giving expecting result because of SPACE.

Error getting:

"Cannot constructQuery '"a b"'. Use expression or multiple clauses instead." EXCEPTION="org.springframework.dao.InvalidDataAccessApiUsageException: Cannot constructQuery '"a b"'. Use expression or multiple clauses instead.

For stopping creation of multiple tokens because of Space. I have mapping:

"userName": {
    "type": "string",
    "index": "not_analyzed"
},

I am totally surprised that I am getting this issue after "index": "not_analyzed" in mapping .

Please help me. Thanks in advance!

Vijay
  • 4,694
  • 1
  • 30
  • 38
  • Hi, when you make your field not analyzed you're actually storing the "raw" field in elasticsearch as you probably know. This error you're getting is "before" your query even being sent to elasticsearch, it's a spring data validation applied for wildcard query methods as you can see at: https://github.com/spring-projects/spring-data-elasticsearch/blob/7f995b38f9a932ba59c3f82e8775161d28139748/src/main/java/org/springframework/data/elasticsearch/core/query/Criteria.java – groo Apr 03 '17 at 12:13
  • Hi ,Thanks for your response , cant we avoid this exception ? I need to use containing method with string having space . – Vijay Apr 04 '17 at 05:50
  • 1
    You're probably looking for a match phrase query that would do what you want: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query-phrase.html But AFAIK this is not available out of the box in spring-data-elasticsearch so you need to implement a custom method: http://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#repositories.custom-implementations where you have access to elastic java API and can implement what you need. If you post a bit more information about your mapping and need I might be able to do an answer with code – groo Apr 04 '17 at 06:03
  • Thank u very much ! – Vijay Apr 05 '17 at 05:13

4 Answers4

3

Actually Spring data apis (containing or startWith) does not work with space in String . I have implemented same with Elastic core api.

NativeSearchQueryBuilder aNativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        aNativeSearchQueryBuilder.withIndices(indexName).withTypes(type);
        final BoolQueryBuilder aQuery = new BoolQueryBuilder();

            aQuery.must(QueryBuilders.queryStringQuery("a b").defaultField("UserName"));

NativeSearchQuery nativeSearchQuery = aNativeSearchQueryBuilder.withQuery(aQuery).build();
        List<Object> aDatas = elasticsearchTemplate.queryForList(nativeSearchQuery, Object.class);
Vijay
  • 4,694
  • 1
  • 30
  • 38
  • When I use this and search for `b`, no results appear. Only when I search for `a` or `a b`, results appear. Seems like query works for a prefix match. – Shubham A. Jun 02 '17 at 10:07
0

You have to mask the spaces:

findByUserNameContaining("a\\ b");
Ant
  • 1
  • 1
0

In my case I just needed to url encode the string so when searching for "a b" just encode it so it becomes "a%20b" then query will be built.

I am using latest springboot version 2.3.*

mark ortiz
  • 659
  • 1
  • 6
  • 13
0

This can be implemented using the expression method in Criteria API

with quotes around the search text for an exact match

criteria.and(new Criteria("FieldName").expression("\"" + SEARCH_TEXT_WITH_SPACE + "\""));

with asterisk around the search text for the wild card match

criteria.and(new Criteria("FieldName").expression("*" + SEARCH_TEXT_WITH_SPACE + "*"));