NEST Suggester errors

Hi all,
I'm trying to get Suggesters up and running.
Using Phrase, Term, or Completion I always get the following error variation.

unable to parse SuggestionBuilder with name [COMPLETION]: parser not found"
unable to parse SuggestionBuilder with name [TERM]: parser not found"
unable to parse SuggestionBuilder with name [PHRASE]: parser not found"

additional error info:
Request failed to execute. Call: Status code 400 from: POST /index-play/searchresult/_search?pretty=true&typed_keys=true. ServerError: Type: named_object_not_found_exception Reason: "[4:21] unable to parse SuggestionBuilder with name [COMPLETION]: parser not found"

I'm having a hard time deciphering the error.
It seems as though the NEST libraries are missing the Suggester parsers?
I have tried multiple 6.x NEST versions and they all have the same issue.
Upgrading to 7.0alpha1 does change the error, but seems to cause a myriad of other issues, and I rather not use an alpha library in production.

I'm currently following this tutorial and working it into my existing code: https://github.com/elastic/elasticsearch-net-example/tree/6.x-codecomplete-netcore#part-6-suggestions

Currently using NES 6.1

Model:
public class SearchResult {

      public SearchResult()
                {
                    TitleSuggest = new CompletionField {Input = new List<string>(Title.Split(' '))};
                }
                public CompletionField TitleSuggest { get; set; }
        //etc
        }

Index Method:

 public async Task<IActionResult> CreateIndex()
        {
            await _searchClient.CreateIndexAsync(SearchIndexName, indexSelector =>
                indexSelector
                    .Mappings(mappingsDescriptor =>
                        mappingsDescriptor.Map<Models.SearchResult>(y => y.AutoMap().Properties(pr=>pr.Completion(c => c.Name(p => p.TitleSuggest)
                        ))))

Suggest Method:

 public async Task<ISearchResponse<SearchResult>> Suggest(string keyword)
        {
return await _searchClient.SearchAsync<SearchResult>(
                s =>
                        s.Suggest(ss => ss
                            .Completion("title", cs => cs
                                .Field(f => f.TitleSuggest)
                                .Prefix(keyword)
                                .Fuzzy(f => f
                                    .Fuzziness(Fuzziness.Auto)
                                )
                                .Size(5))
}

Any insight would be great, thanks!

What version of Elasticsearch are you running against? Also, can you capture what the client is sending with Fiddler or OnRequestCompleted() and add it here?

Hi @forloop

We are using version 6.7.0. I attempted the solution with the latests NEST libraries as well which was 6.6.0. Might be a good idea to sync those up.

Here's the Direct Stream
Does this have the information you are looking for?

Here's one using Phrase Suggest, and the exception is complaining the Text Property is not supported. Removing that leads me back to the "named_object_not_found_exception"

 Audit trail of this API call:
 - [1] BadResponse: Node: http://lb-xxxxxxxxxxxxxxx.south-centralus.cloudapp.azure.com:9200/ Took: 00:00:00.5558710
OriginalException: Elasticsearch.Net.ElasticsearchClientException: Request failed to execute. Call: Status code 400 from: POST /_searchresults/searchresult/_search?pretty=true&typed_keys=true. ServerError: Type: parsing_exception Reason: "suggestion does not support [TEXT]"
Request:
{
  "suggest": {
    "person-suggest": {
      "TEXT": "For",
      "PHRASE": {
        "field": "TITLESUGGEST",
        "size": 3
      }
    }
  }
}
# Response:
{
  "error" : {
    "root_cause" : [
      {
        "type" : "parsing_exception",
        "reason" : "suggestion does not support [TEXT]",
        "line" : 4,
        "col" : 15
      }
    ],
    "type" : "parsing_exception",
    "reason" : "suggestion does not support [TEXT]",
    "line" : 4,
    "col" : 15
  },
  "status" : 400
}


{
"suggest":{
"person-suggest":{
"TEXT":"For",
"PHRASE":{
"field":"TITLESUGGEST",
"size":3
}
}
}
}

Here's one with the Completion Suggest. It was complaining "Prefix" was not supported. Removing that, I got the "named_object" exception again.

# OriginalException: Elasticsearch.Net.ElasticsearchClientException: Request failed to execute. Call: Status code 400 from: POST /_searchresults/searchresult/_search?pretty=true&typed_keys=true. ServerError: Type: named_object_not_found_exception Reason: "[4:21] unable to parse SuggestionBuilder with name [COMPLETION]: parser not found"
# Request:
{
  "suggest": {
    "title": {
      "COMPLETION": {
        "field": "TITLESUGGEST",
        "size": 5,
        "fuzzy": {
          "fuzziness": "AUTO"
        }
      }
    }
  }
}
# Response:
{
  "error" : {
    "root_cause" : [
      {
        "type" : "named_object_not_found_exception",
        "reason" : "[4:21] unable to parse SuggestionBuilder with name [COMPLETION]: parser not found"
      }
    ],
    "type" : "named_object_not_found_exception",
    "reason" : "[4:21] unable to parse SuggestionBuilder with name [COMPLETION]: parser not found"
  },
  "status" : 400
}


{
"suggest":{
"title":{
"COMPLETION":{
"field":"TITLESUGGEST",
"size":5,
"fuzzy":{
"fuzziness":"AUTO"
}
}
}
}
}

Here is the (pruned) response from the server using the Phrase Suggest.

{
shards = null,
    aggregations = {},
    aggs = {},
    profile = null,
    suggest = {},
    took = 0,
    timedOut = false,
    terminatedEarly = false,
    scrollId = null,
    hitsMetadata = null,
    numberOfReducePhases = 0,
    total = 0,
    maxScore = 0,
    documents = [],
    hits = [],
    fields = [],
    serverError = {
        error= {
            headers= {},
            rootCause=[
                {
                    causedBy= null,
                    metadata= {
                        ...
                    },
                    reason= "suggestion does not support [TEXT]",
                    stackTrace= null,
                    type= "parsing_exception"
                }
            ],
            causedBy= null,
            metadata= {
                ...
            },
            reason= "suggestion does not support [TEXT]",
            stackTrace= null,
            type= "parsing_exception"
        },
        status= 400
    },
    isValid = false,
    apiCall = {
        auditTrail=[
            {
                ended= "2019-05-13T16=35=38.29013Z",
                event= 9,
                exception= null,
                node= {
                    clientNode= false,
                    deadUntil= "0001-01-01T00=00=00",
                    failedAttempts= 0,
                    holdsData= true,
                    httpEnabled= true,
                    id= null,
                    ingestEnabled= false,
                    isAlive= true,
                    isResurrected= false,
                    masterEligible= true,
                    masterOnlyNode= false,
                    name= null,
                    settings= {},
                    uri= "..."
                },
                path= "...",
                started= "2019-05-13T16=35=37.664307Z"
            }
        ],
        debugInformation= "Unsuccessful low level call on POST= /_searchresults/searchresult/_search?pretty=true&typed_keys=true # Audit trail of this API call= - [1] BadResponse= Node= http=//lb-xxxxxxxxxxxxxxx.south-centralus.cloudapp.azure.com=9200/ Took= 00=00=00.6258230 # OriginalException= Elasticsearch.Net.ElasticsearchClientException= Request failed to execute. Call= Status code 400 from= POST /_searchresults/searchresult/_search?pretty=true&typed_keys=true. ServerError= Type= parsing_exception Reason= "suggestion does not support [TEXT
        ]" # Request= { "suggest"= { "person - suggest"= { "TEXT"= "For", "PHRASE"= { "field"= "TITLESUGGEST", "size"= 3 } } } } # Response= { "error" = { "root_cause" = [ { "type" = "parsing_exception", "reason" = "suggestion does not support [TEXT
        ]", "line" = 4, "col" = 15 } ], "type" = "parsing_exception", "reason" = "suggestion does not support [TEXT
        ]", "line" = 4, "col" = 15 }, "status" = 400 } ",
        deprecationWarnings=[],
        httpMethod= 1,
        httpStatusCode= 400,
        ...
            failureReason= 1,
            request= {
                accept= "application/json",
                allowedStatusCodes=[],
                basicAuthorizationCredentials= {
                    password= "...",
                    username= "..."
                },
                ...
                node= {
                    clientNode= false,
                    deadUntil= "0001-01-01T00=00=00",
                    failedAttempts= 0,
                    holdsData= true,
                    httpEnabled= true,
                    id= null,
                    ingestEnabled= false,
                    isAlive= true,
                    isResurrected= false,
                    masterEligible= true,
                    masterOnlyNode= false,
                    name= null,
                    settings= {},
                    uri= "..."
                },
                onFailureAuditEvent= 9,
                onFailurePipelineFailure= 1,
                pathAndQuery= "...",
                pingTimeout= "00=00=02",
                pipelined= true,
                postData= {
                    disableDirectStreaming= true,
                    type= 4,
                    writtenBytes= "e..."
                },
                ...
            },
            ...
        },
        ...
    },

    ...

}

The serialized suggester JSON has capitalized fields within it, which it should not have. How are you configuring the client and ConnectionSettings?

1 Like

That was it!
I had the DefaultFieldNameInferrer set to UpperCase for some reason.
Thanks!

private IElasticClient ElasticClient(IConfiguration _config, string defaultIndex)
{
  var settings = new ConnectionSettings(new Uri(_config.GetSection("Search:Url").Value))
    .BasicAuthentication(_config.GetSection("Search:User").Value, _config.GetSection("Search:Password").Value)
    .DefaultIndex(_config.GetSection(defaultIndex).Value);
  //settings.DefaultFieldNameInferrer(p => p.ToUpper(CultureInfo.CurrentCulture));

  //Enable ElasticSearch Debugging
  settings.PrettyJson().DisableDirectStreaming();

  return new ElasticClient(settings);
}

Thank you for opening this question as it highlighted an issue in the serialization of suggesters when a DefaultFieldNameInferrer delegate is specified.

I've opened a PR to address :+1:

1 Like

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