5

I'm seriously struggling with a query in Elastic search so i'm hoping someone here can help me.

So I have an Index in elastic search which stores some basic info on a user. Then I have my Spring Boot API which allows a client to search on said index.

In my app, when a user signs up they get to choose a displayname on the site. Now when they type out a display name I want to be able to check elastic and tell them if its taken or not.

However, where I'm struggling is, say I have One user in my Index with the DisplayName of "John Boy", now user two signs up and wants the display name "Boy". When I do a search to see if "Boy" is taken, I get back "John Boy". I want it so the query tells me if "Boy" is free and not care if "John Boy" is taken.

I thought I was just getting my head around ES but maybe not, I was under the impression that the field (see index mapping below) keyword I could do a term search and get back the exact match?

Below I've included my Pojo and my ES index mapping. Please if anyone can help me....thanks for reading:

Search Method

  public long checkUserNameAvailability(String query) {

        QueryBuilder matchSpecificFieldQuery= QueryBuilders
                .termQuery("displayName", query);

                Query searchQuery = new NativeSearchQueryBuilder()
                .withFilter(matchSpecificFieldQuery)
                .build();

        SearchHits<UserProfile> searchSuggestions =
                elasticsearchOperations.search(searchQuery,
                        UserProfile.class,
                        IndexCoordinates.of(elasticUserIndex));

        List<UserProfile> suggestions = new ArrayList<>();

        return searchSuggestions.getTotalHits();
    }

Pojo

@Getter
@Setter
@Document(indexName = "userprofiles")
public class UserProfile {

    @Field(type = FieldType.Text, name = "userId")
    private String userId;

    @Field(type = FieldType.Keyword, name = "displayName")
    private String displayName;

    @Field(type = FieldType.Text, name = "name")
    private String name;

}

ES Mapping

{
  "userprofiles": {
    "mappings": {
      "properties": {
        "displayName": {
          "fields": {
            "keyword": {
              "ignore_above": 256,
              "type": "keyword"
            }
          },
          "type": "text"
        },
        "name": {
          "fields": {
            "keyword": {
              "ignore_above": 256,
              "type": "keyword"
            }
          },
          "type": "text"
        },
        "userId": {
          "fields": {
            "keyword": {
              "ignore_above": 256,
              "type": "keyword"
            }
          },
          "type": "text"
        }
      }
    }
  }
}

Side note: I'm using Spring boot version 2.4.3

And

    compile('org.springframework.boot:spring-boot-starter-data-elasticsearch')
    compile group: 'org.springframework.data', name: 'spring-data-elasticsearch', version: '4.1.5'

Once again many thanks

1
  • hi, interesting, perhaps exact match query instead of term query might help
    – jspcal
    Commented Apr 1, 2021 at 23:58

2 Answers 2

2

Maybe you should use keyword query, because 'displayName' field type is text, it will be analyzer in both query and index.

QueryBuilder matchSpecificFieldQuery= QueryBuilders
                .termQuery("displayName.keyword", query);
2
  • Excellent thank you! Is there away to make the term query case insensitive?
    – MetaCoder
    Commented Apr 2, 2021 at 5:35
  • Ok, I recreated my index to set "normalizer": "case_insensitive_normalizer" and then performed a match query and it now works as expected. Cant thank you enough for the help
    – MetaCoder
    Commented Apr 2, 2021 at 6:48
2

I think you shuld reconsider the type of query you are using. Try using a simple match on the .keyword field.

1
  • Cant thank you enough Matab, I was honestly going out of my mind
    – MetaCoder
    Commented Apr 2, 2021 at 6:49

Not the answer you're looking for? Browse other questions tagged or ask your own question.