Mohsen Esmailpour
Mohsen Esmailpour

Reputation: 11554

Search for sub string that contains dash and space in EleasticSearch

I have a model like this:

public class PersonModel
{
    public Guid Id { get; set; }

    public PersonageType Type { get; set; }

    public string Name { get; set; }

    public string NationalCode { get; set; }

    public string BourseCode { get; set; }
}

I'm trying to implement a query to filter data that match the substring of each property:


var result = await ElasticClient.SearchAsync<PersonModel>(sd => sd
    .Index(IndexName)
    .From((pagination.PageNumber - 1) * pagination.PageSize)
    .Size(pagination.PageSize)
    .Query(q =>
        +q.Match(m => m.Field(f => f.Type).Query(typeValue)) &&
        +q.Wildcard(w => w.Field(f => f.NationalCode).Value(nationalCode == null ? null : $"*{nationalCode}*")) &&
        +q.Wildcard(w => w.Field(f => f.Name).Value(name == null ? null : $"*{name}*")) &&
        +q.Wildcard(w => w.Field(f => f.BourseCode).Value(bourseCode == null ? null : $"*{bourseCode}*"))));

This query works fine but when each value contains - or white space, nothing will be returned. For example, I have a person with the name john doe and when name value is hn d, the search query doesn't work.

Upvotes: 0

Views: 445

Answers (2)

Mohsen Esmailpour
Mohsen Esmailpour

Reputation: 11554

As @hamid said keyword fixed the problem and I changed the query to this:

var result = await ElasticClient.SearchAsync<PersonageSearchReadModel>(sd => sd
    .Index(IndexName)
    .From((pagination.PageNumber - 1) * pagination.PageSize)
    .Size(pagination.PageSize)
    .Query(q =>
        +q.Match(m => m.Field(f => f.Type).Query(typeValue)) &&
        +q.Wildcard(w => w.Field(f => f.NationalCode.Suffix("keyword")).Value(nationalCode == null ? null : $"*{nationalCode}*")) &&
        +q.Wildcard(w => w.Field(f => f.Name.Suffix("keyword")).Value(name == null ? null : $"*{name}*")) &&
        +q.Wildcard(w => w.Field(f => f.BourseCode.Suffix("keyword")).Value(bourseCode == null ? null : $"*{bourseCode}*"))));

Upvotes: 3

hamid bayat
hamid bayat

Reputation: 2179

the easiest approach for solving this problem is to change your mapping. try something as below:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "NationalCode": {
        "type":  "keyword"
      },
      "Name": {
        "type":  "keyword"
      },
      "BourseCode": {
        "type":  "keyword"
      },
    }
  }
}

then reindex your data.

for more information: https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html

I think you are using text field datatype. also if you want to use match query and enjoy its benefits you can have both type as below:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "NationalCode": { 
        "type": "text",
        "fields": {
          "keyword": { 
            "type": "keyword"
          }
        }
      }
    }
  }
}

then you can use match query against NationalCode and wildcard query against NationalCode.keyword

Upvotes: 2

Related Questions