matchnestelasticsearch-queryterm-query

NEST is not returning values for an exact search


I am trying to build a dynamic query using NEST which is as under

string product = "goldpgl";            
string agencyid = "1123";


    ISearchResponse <ProductModel> res = client().Search<ProductModel>(s => s
        .Index("proddata")
        .From(0)
        .Size(100)
        .Query(q =>                            
                    +q.Term(p => p.product, product) &&                           
                    +q.Term(p => p.agencyid, agencyid)));

If I pass, product value = "GoldPGL" [ N.B.~ Real value in the index ], I am not able to find the result.

However, if I pass the value in lowercase like "goldpgl", it works.

Also, it does not work for values like "Gold - PGL" or "SOME OTHER LOAN".

My POCO is as under

public class ProductModel
    {
        public string product { get; set; }
        public string agencyid { get; set; }

    }

What is wrong and how to rectify this?


Solution

  • As you have not provided the mapping and search query, I am assuming its happening because you are using the term query not the match query.

    Term queries are not analyzed means whatever you entered in your search query would be matched against the tokens in the index. And by default, all the text fields in Elasticsearch use the standard analyzer which converts tokens to lowercase. hence GoldPGL doesn't match while goldpgl matches in your term query.

    While match query as explained the official document is analyzed query and the same analyzer is applied on the search term, which is applied at index time, hence GoldPGL as well as goldpgl converted to goldpgl and both the query matches the documents and same is with Gold - PGL which also matches and verifies by me.

    Analyze API comes very handy to troubleshoot these types of issue, where search query doesn't match the indexed tokens and one example of how GOLDPGL would be analyzed is shown below:

    POST /_analyze

    {
        "text": "GOLDPGL",
        "analyzer" : "standard"
    }
    
    {  "token": "goldpgl",}
    
    {
        "text": "GOLD - PGL",
        "analyzer" : "standard"
    }
    
    {
                "token": "gold",
                "start_offset": 0,
                "end_offset": 4,
                "type": "<ALPHANUM>",
                "position": 0
            },
            {
                "token": "pgl",
                "start_offset": 7,
                "end_offset": 10,
                "type": "<ALPHANUM>",
                "position": 1
            }
    

    I reproduced your issue and as I am not familiar with NEST, showing your example using the REST API.

    Index Def

    POST /

    {
        "mappings": {
            "properties": {
                "product": {
                    "type": "text"
                }
            }
        }
    }
    

    Index some documents


    POST //_doc/1

    {
        "product": "GoldPGL"
    }
    

    Index 2nd doc

    {
        "product": "Gold - PGL"
    }
    

    Now search query using term query(as shown in your example), doesn't return any result (when GoldPGL is used)

    {
        "query": {
            "term": {
                "product": {
                    "value": "GoldPGL"
    
                }
            }
        }
    }
    

    When used goldgpl, it gives result

    {
        "query": {
            "term": {
                "product": {
                    "value": "goldpgl"
    
                }
            }
        }
    }
    

    Result

    "hits": [
                {
                    "_index": "so-term-nest",
                    "_type": "_doc",
                    "_id": "1",
                    "_score": 0.8025915,
                    "_source": {
                        "product": "GoldPGL"
                    }
                }
            ]
    

    Solution (use match query)

    {
        "query": {
            "match" : {
                "product" : {
                    "query" : "GoldPGL"
                }
            }
        }
    }
    

    and this return results

    "hits": [
                {
                    "_index": "so-term-nest",
                    "_type": "_doc",
                    "_id": "1",
                    "_score": 0.8025915,
                    "_source": {
                        "product": "GoldPGL"
                    }
                }
            ]