Get response from custom Solr requestHandler with .NET

This is a follow-up to my previous post: Configuring Solr to provide search suggestions

So everything is set up in Solr, but now we need to get the response in our .NET code.

Assuming the following:

using Newtonsoft.Json.Linq;
using SolrNet.Impl;
var solrRoot = "http://localhost:3664/solr";
var suggestIndexName = "suggest_index";
var requestHandlerName = "/suggest";
var suggestUrl = string.Format("/{0}{1}", suggestIndexName, requestHandlerName);

All we need to do is set up the querystring parameters, instantiate the SolrConnection and do a GET.

var query = new SuggestQuery
{
   SuggestTerm = "partial string to get suggestions for",
   PageSize = 10
};
var parameters = new Dictionary<string, string>
{
   {"q", query.SuggestTerm}, // the string we're getting suggestions for
   {"wt", "json"}      // the response format, can also be "xml"
}
var solrConnection = new SolrConnection(solrRoot);

var response = solrConnection.Get(suggestUrl, parameters);

In this case the response is a json string. I used Newtonsoft.Json to parse the response into a JObject. Then I can traverse the fields/nodes and finally cast the suggestions into a concrete type.

Since I have two suggesters set up (a Fuzzy suggester and an Infix suggester), I’ll get two sets of suggestions. My SolrSuggest Suggestion type is set up with overrides for Equals and GetHashCode to facilitate the comparing of these items. This way I can do a .Union on the two lists to remove duplicate terms, then it can be ordered and truncated (page size or max count).

var response = new SolrSuggest(); // custom type defined below

var responseHeader = JObject.Parse(solrSuggestReponse); // Newtonsoft.JObject
var suggestions = responseHeader["suggest"];

var infixSuggester = suggestions["infixSuggester"];
var infixTermSuggestions = infixSuggester[query.SuggestTerm]; // this field will have the name of the term that was searched.

var infix = jsDeserializer.Deserialize<SolrSuggest>(infixTermSuggestions.ToString()); // Deserialize to custom Type

var fuzzySuggester = suggestions["fuzzySuggester"];
var fuzzyTermSuggestions = fuzzySuggester[query.SuggestTerm]; // this field will have the name of the term that was searched.

var fuzzy = jsDeserializer.Deserialize<SolrSuggest>(fuzzyTermSuggestions.ToString());

// .Union will add items from the second list to the first list while comparing them to prevent the addition of duplicate items
response.suggestions = infix.suggestions.Union(fuzzy.suggestions).OrderByDescending(s => s.weight).Take(query.PageSize).ToList();

response.numFound = response.suggestions.Count;

return response;

And this is the structure I used to deserialize the TermSuggestions to C# objects:

public class Suggestion
{
   public string term { get; set; }
   public int weight { get; set; }
   public string NormalizedTerm
   {
      // The infix suggester will wrap the suggest term within the suggestions in <b> tags
      get { return term.Replace("<b>", string.Empty).Replace("</b>", string.Empty); }
   }

   public override bool Equals(object otherSuggestion)
   {
      var other = (Suggestion)otherSuggestion;
      return other != null && other.NormalizedTerm == NormalizedTerm;
   }

   public override int GetHashCode()
   {
      return NormalizedTerm.GetHashCode();
   }
}

public class SolrSuggest
{
   public int numFound { get; set; }
   public List<Suggestion> suggestions { get; set; }
   public SolrSuggest()
   {
      suggestions = new List<Suggestion>();
   }
}

Thanks for reading, I hope this helps someone out there.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

Up ↑

%d bloggers like this: