Exact match query not returning expected results

I am trying to implement an exact match query with NEST for ElasticSearch. My expected results are to retrieve owner names that exactly matches the search criteria. However, that actual results of my query are partial matches. My query is:

 public class Account_ES
{
   public int owner_id { get; set; }
   public string owner_full_name {get;set;}

    ...
}

var searchCriteria = "Bob Jones";

var sr_account_owner_search = new SearchDescriptor<Account_ES>()
                
                 .Index("accounts_1").Take(10000)                 
                 .Query(q => q.ConstantScore(m=>m.Filter(ff=>ff.Match(fff=>fff.Field(dd=>dd.owner_full_name).
Query(searchCriteria))))).Sort(ss => ss.Field(sss => sss.Field("owner_id"))).
              Highlight(h => h.Fields(f => f.Field("owner_full_name").
PreTags("<span class='hit' style='background-color:yellow'>").PostTags("</span>")));

Instead of exact matches for "Bob Jones" I get results including:

Bob Stevens

Larry Jones

Jennifer Jones

Any ideas what the issue might be?

You are doing a match query, that bu default is an OR combined query. Change the operator to AND to make sure both terms are included in results of your query.

Thanks so much for the incredible help. Changing the operator to AND generated results that were a lot better, but still not exact. For example, searching for "Jones Larry" should return no results, however it is returning

Larry Jones

I am trying to implement exact match like when putting search criteria in double quotes in google. Using the Operator AND in my code so far, looks like:

 public class Account_ES
{
   public int owner_id { get; set; }
   public string owner_full_name {get;set;}

    ...
}

var searchCriteria = "Bob Jones";

var sr_account_owner_search = new SearchDescriptor<Account_ES>()
                
                 .Index("accounts_1").Take(10000)                 
                 .Query(q => q.ConstantScore(m=>m.Filter(ff=>ff.Match(fff=>fff.Field(dd=>dd.owner_full_name).Operator(Operator.And).
Query(searchCriteria))))).Sort(ss => ss.Field(sss => sss.Field("owner_id"))).
              Highlight(h => h.Fields(f => f.Field("owner_full_name").
PreTags("<span class='hit' style='background-color:yellow'>").PostTags("</span>")));

Take a look at phrase queries for exact matches, where the terms are next to each other.

1 Like

Thanks for the awesome help. I've got working code now for exact matches..similar to:

public class Account_ES
{
   public int owner_id { get; set; }
   public string owner_full_name {get;set;}

    ...
}

var searchCriteria = "Bob Jones";

var sr_account_owner_search = new SearchDescriptor<Account_ES>()
                
                 .Index("accounts_1").Take(10000)      

  .Query(mm=>mm.MatchPhrase(c => c
    .Field(f=>f.owner_full_name)
    .Analyzer("standard")
    .Boost(1.1)
    .Query(searchCriteria)
    .Slop(2)
    .Name("named_query")
)).Sort(ss => ss.Field(sss => sss.Field("owner_id"))).Highlight(h => h.Fields(f => f.Field("*").PreTags("<span class='hit' style='background-color:yellow'>").PostTags("</span>")));

I was mistaken. After further testing, the match phrase does not work as I have written it. It still returns the following when searching for "Jones Larry". I think the phrase query might work in combination with keyword type fields -- I will try that.

Larry Jones

Thank you, @spinscale for the help. Your input got me thinking, and I was able to come up with a solution with Keyword and Term. The way the developer created my index allows for this.

it is mapped as:

....
   },
        "owner_full_name": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },

...

I was then able to get the query working with this NEST -- I might have to clean it up, but it is currently working.

public class Account_ES
{
   public int owner_id { get; set; }
   public string owner_full_name {get;set;}

    ...
}

var searchCriteria = "Bob Jones";

var sr_account_owner_search = new SearchDescriptor<Account_ES>()
                
                 .Index("accounts_1").Take(10000)   
.Query(mm=>mm.Bool(vv=>vv.Must(ee=>ee.Bool(bb=>bb.Should(tt=>
tt.Term(gg=>gg.Field(ff=>ff.owner_full_name.Suffix("keyword")).Value(searchCriteria)
)))))).Sort(ss => ss.Field(sss => sss.Field("owner_id"))).Highlight(h => h.Fields(f => f.Field("*").PreTags("<span class='hit' style='background-color:yellow'>").PostTags("</span>")));

A search for "Jones Larry" now returns nothing. While search for "Larry Jones" returns records.

Keep in mind, that keyword and term search is also fully case sensitive. So if the user input is Larry JoneS nothing will be returned. If you can deal with that fine, otherwise keep thinking about using analyzers and make your data ready for full text search.

That said, using keyword will be a lot faster!

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.