How do I highlight search results in Solr?

  • Page Owner: Not Set
  • Last Reviewed: 2021-03-05

I don't want to this manually. Does Solr support this?


Answer

Yes, in you're Solr config you can add a formatter to your results:

      <formatter name="html"
                 default="true"
                 class="solr.highlight.HtmlFormatter">
        <lst name="defaults">
          <str name="hl.simple.pre"><![CDATA[<em>]]></str>
          <str name="hl.simple.post"><![CDATA[</em>]]></str>
        </lst>
      </formatter>

You can adjust the CDATA elements to whatever markup you'd like.


Additional Posts

Here was my experience with trying to use SOLR highlighting and why I ended up just doing a string replace. And this may just be specific to how we have access to highlighted results in SolrNet.

In order activate highlighting in SolrNet you can include .ExtraParams("hl", "on") as an extra parameter and then in your results you should have access to the highlights in your results object at .Results.Highlights.

The Highlights result in SolrNet is a IDictionary<string, HighlightedSnippets> where the string is the SOLR id field for the document and the HighlightedSnippets is basically a list of SOLR fields and a list of matching highlighted text for that field.

So my frustration with that is every time I loop through my results I have to go check this dictionary for a matching id, then I have to loop through the fields with highlights and see if there are any that I'm displaying and then display that text. Which is annoying but was working. What I ran into that kind of pushed things from annoying to where I just decided to do a string replace is where I had a ICollection<string> property. So what I was doing was joining the items in the collection with a ',' and displaying that in the results. Well if there happened to be a highlighted word in that collection, I then needed to find that highlight or highlights in the HighlightedSnippets object and replace the non highlighted results in the original string collection then do my string join. It was at that point I decided to just do a string replace because I didn't see the benefit of trying to find highlights from SolrNet.

I ended up writing these two extension methods:

public static string HighlightText(this string Source, string SearchText)
{
  if (!Source.HasValue())
     return string.Empty;

  if (!SearchText.HasValue())
     return Source;

  return Regex.Replace(Source, SearchText, new MatchEvaluator(ReplaceKeyWords), RegexOptions.IgnoreCase);
}

public static string ReplaceKeyWords(Match m)
{
  return "<b>" + m.Value + "</b>";
}

Basically any field you want to highlight text on you just call the extension method and pass in the searched term: result.Title.HighlightText(Model.SearchTerm)

This will do a regex replace on the string that is passed into it maintaining the capitalization of the match and return it wrapped in HTML. This does need to be wrapped in Html.Raw() when called.

Anyway it just feels way simpler to just replace the text on the actual results then to try and dig through a dictionary just to identify something that we can easily find outselves. I'm happy to have somebody tell me why SolrNet's highlights are better ¯\_(ツ)_/¯