Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ElasticsearchOperations query not returning exact matches

Tags:

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

like image 507
MetaCoder Avatar asked Apr 01 '21 23:04

MetaCoder


2 Answers

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);
like image 92
yi jiang Avatar answered Oct 04 '22 12:10

yi jiang


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

like image 38
Matan Baruch Avatar answered Oct 04 '22 11:10

Matan Baruch