Customizing Solr Highlighting with Sunspot
Need full-text text search in your web app? You don’t have to use Elasticsearch. There are alternatives. Even in 2025, some will refuse to switch to Elasticsearch, preferring to use venerable tools such as Solr instead.
Recently, I worked on a Ruby on Rails project that used Solr and Sunspot to interface with Solr. I was given a particular task to customize how much text is shown around a word the user was searching for - in other words, to change the size of the highlight fragment. But only for one field for one particular model - and that made things tricky!
Let’s see how I managed.
Changing the Highlight Fragment Size
Ad-hoc changes to the fragment size can be made using solr_params
.
search = Sunspot.new_search(@all_entities) do
# Adjust the fragment size from its default of 100
adjust_solr_params do |solr_params|
solr_params['hl.fragsize'] = 300
end
end
search = search.execute
@results = search.hits
However, this would change the fragment size for all searches. Let’s say we have a particular model and want to adjust the fragment size only for searches concerning that model.
class Post < ApplicationRecord
searchable do
integer(:id)
text(:title, stored: true)
text(:content, stored: true)
string(:class_name) do
self.class.name
end
end
end
To change the highlight fragment size for content, but not for the title, we can adjust solr_params
to include the field size. Note that fields are generally postfixed with texts
.
search = Sunspot.new_search(@all_entities) do
adjust_solr_params do |solr_params|
solr_params['hl.content_texts.fragsize'] = 300
end
end
That works - but only if there are no other models with a content
field. If you have multiple models with the same field names, all of those would be affected. We need to make one last change: change the name with which the content field is indexed.
class Post < ApplicationRecord
searchable do
# Content will now be indexed as post_content_texts
text(:content, stored: true, as: :post_content_texts)
end
end
search = Sunspot.new_search(@all_entities) do
adjust_solr_params do |solr_params|
solr_params['hl.post_content_texts.fragsize'] = 300
end
end
And there you have it. Easy enough in hindsight 🙂