Search code examples
c#elasticsearchnest

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.


Solution

  • 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