Need help with suggest in NEST

Hi

Using C# Nest client
Elasticsearch 6.3

I'm attempting to add suggest when search queries return zero results. However, I get this error message UnexpectedElasticsearchClientException: Error setting value to 'Suggest' on 'Nest.SearchResponse when I do. If I remove the suggest section I have no problems with the Nest client, as soon as I add it back in and it tries to serialize the results into my FunIndexItem it bombs out.

ms.Search<FunIndexItem>(s => s
		.Index("fun")
		.SearchType(SearchType.DfsQueryThenFetch)
		.Suggest(ss => ss
			.Phrase("person-suggest", p => p
				.Field(f => f.Owner)
				.Size(3)
				.Text(queryRequest.SearchTerm)
			)
			.Term("page-suggest", p => p
			    .Field(f => f.Page)
			    .Size(3)
			    .Text(queryRequest.SearchTerm)
			)
		)
		.Query(q => q
                          .QueryString(qs => qs
								.Query(queryRequest.SearchTerm) ......... etc

My poco object:

[ElasticsearchType(Name = "fun")]
public class FunIndexItem 
{	
	public SuggestDictionary<FundraiserIndexItem> Suggest {get; set; }	
	public DateTime? CreatedDate { get; set; }
	[Text(Analyzer = IndexAnalysers.Snowball, SearchAnalyzer = IndexAnalysers.Snowball)]
	public string Page { get; set; }
	[Text(Analyzer = IndexAnalysers.Snowball, SearchAnalyzer = IndexAnalysers.Snowball)]
	public string Name { get; set; }	
	public string Owner  { get; set; }
	public string Country { get; set; }
	public string CountryCode { get; set; }
}

Exception message

Message
Error setting value to 'Suggest' on 'Nest.SearchResponse`1[FundraiserIndexItem]'. 

Debug Error Message

# FailureReason: Unrecoverable/Unexpected BadResponse while attempting POST on https://xxxxxxxxx.com/_msearch?typed_keys=true
 - [1] BadResponse: Node: https://xxxxxxxxx.com/ Exception: JsonSerializationException Took: 00:00:00.1565101
# Audit exception in step 1 BadResponse:
Nest.Json.JsonSerializationException: Error setting value to 'Suggest' on 'Nest.SearchResponse`1[FundraiserIndexItem]'. ---> System.InvalidCastException: [A]Nest.SuggestDictionary`1[FundraiserIndexItem] cannot be cast to [B]Nest.SuggestDictionary`1[FundraiserIndexItem]. 
Type A originates from 'Nest, Version=6.0.0.0, Culture=neutral, PublicKeyToken=96c599bbe3e70f5d' in the context 'LoadFrom' at location 'C:\Users\jasman\AppData\Local\LINQPad\NuGet.FW46\NEST 6.3.1\NEST.6.3.1\lib\net461\Nest.dll'. 
Type B originates from 'Nest, Version=6.0.0.0, Culture=neutral, PublicKeyToken=96c599bbe3e70f5d' in the context 'LoadFrom' at location 'C:\Users\jasman\AppData\Local\LINQPad\NuGet.FW46\NEST 6.3.1\NEST.6.3.1\lib\net461\Nest.dll'.
           at SetSuggest(Object , Object )
           at Nest.Json.Serialization.DynamicValueProvider.SetValue(Object target, Object value)
           --- End of inner exception stack trace ---
           at Nest.Json.Serialization.DynamicValueProvider.SetValue(Object target, Object value)
           at Nest.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
           at Nest.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
           at Nest.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
           at Nest.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
           at Nest.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
           at Nest.Json.Serialization.JsonSerializerProxy.DeserializeInternal(JsonReader reader, Type objectType)
           at Nest.Json.Linq.JToken.ToObject(Type objectType, JsonSerializer jsonSerializer)
           at Nest.Json.Linq.JToken.ToObject[T](JsonSerializer jsonSerializer)
           at Nest.MultiSearchResponseJsonConverter.CreateSearchResponse[T](SearchHitTuple tuple, JsonSerializer serializer, IDictionary`2 collection)
           at lambda_method(Closure , SearchHitTuple , JsonSerializer , IDictionary`2 )
           at Nest.MultiSearchResponseJsonConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
           at Nest.MultiSearchResponseJsonConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
           at Nest.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)
           at Nest.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
           at Nest.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
           at Nest.Json.JsonSerializer.Deserialize[T](JsonReader reader)
           at Nest.InternalSerializer.Deserialize[T](Stream stream)
           at Nest.ElasticClient.<>c__DisplayClass515_1.<MultiSearch>b__1(IApiCallDetails r, Stream s)
           at Elasticsearch.Net.ResponseBuilder.SetBody[TResponse](ApiCallDetails details, RequestData requestData, Stream responseStream, String mimeType)
           at Elasticsearch.Net.ResponseBuilder.ToResponse[TResponse](RequestData requestData, Exception ex, Nullable`1 statusCode, IEnumerable`1 warnings, Stream responseStream, String mimeType)
           at Elasticsearch.Net.HttpWebRequestConnection.Request[TResponse](RequestData requestData)
           at Elasticsearch.Net.RequestPipeline.CallElasticsearch[TResponse](RequestData requestData)
           at Elasticsearch.Net.Transport`1.Request[TResponse](HttpMethod method, String path, PostData data, IRequestParameters requestParameters)

Any ideas where I am going wrong?

On your POCO that represents a document to be indexed in Elasticsearch, you should use CompletionField as the property type to provide input values to a Completion Suggester. For example,
here's a Question type that maps to a Stackoverflow question

public class Question : Post
{
    public string Title { get; set; }

    public CompletionField TitleSuggest { get; set; }

    public int? AcceptedAnswerId { get; set; }

    public int ViewCount { get; set; }

    public string LastEditorDisplayName { get; set; }

    public List<string> Tags { get; set; }

    public int AnswerCount { get; set; }

    public int FavoriteCount { get; set; }

    public DateTimeOffset? CommunityOwnedDate { get; set; }

    public override string Type => nameof(Question);
}

For reading the suggester results on a search response, you can index into the SuggestDictionary<T> on the response

var client = new ElasticClient();

var input = "wh";

var response = client.Search<Question>(s => s
	.Index<Question>()
    .Suggest(su => su
		.Completion("title", cs => cs
			.Field(f => f.TitleSuggest)
			.Prefix(input)
			.Fuzzy(f => f
				.Fuzziness(Fuzziness.Auto)
			)
			.Size(5)
		)
    )
);

var suggestions =
    from suggest in response.Suggest["title"]
    from option in suggest.Options
    select new
    {
        Id = option.Source.Id,
        Text = option.Text,
        Votes = option.Score
    };
1 Like

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