Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How highlight found word with Sunspot?

I want to highlight found words in text, for example, as shown here.

As far as I know I must follow these steps:

1) In my model, I must add :stored => true option to the field which I want to highlight:

searchable do 
    text :title, :stored => true
    text :description
end

2) In my controller, I have to declare which field I want highlighted:

def search
    @search = Article.search do
        keywords params[:search] do
            highlight :title
        end
    end
end

3) In the view I'm not sure what to do, I tried this:

- @search.each_hit_with_result do |hit, result|
    %p= link_to raw(hit_title(hit)), article_path(result)

It is what doing method hit_title:

def hit_title(hit)
    if highlight = hit.highlight(:title)
        highlight.format { |word| "<font color='green'>#{word}</font>" }
    else
        h(hit.result.title)
    end
end

But it doesn't work as expected, it always highlights the first word of the title, even if the searched word is at the end of it.

Is there an easier way to do this?

like image 816
zolter Avatar asked Nov 05 '22 15:11

zolter


2 Answers

I bumped into this looking for a solution to render highlights from sunspot search on rails view.

I didn't find much of a ready solution anywhere, so I used part of this post to make one of my one. I am quite new to rails so this might not be fully the RoR way.

In my case, I did a full text search on two fields, call them notes and description.

In order to be able to render to html the highlights, I introduced a hash of values containing the id of the record, the name of the column and its highlighted value, adequately formatted. This allows me to highlight the search results on different fields.

entry.rb:

searchable do
    text :description, :stored => true
    text :notes, :stored => true
end

entries_controller.rb:

@search = Entry.search
    if params[:search].nil? || params[:search].empty?
        stext=''
    else
        stext=params[:search]
    end
    fulltext stext, :highlight => true
    paginate(page: params[:page], :per_page => 10)
end
@[email protected]

@results=Hash.new
@search.hits.each do |hit|
    hit.highlights(:description).each do |highlight|
        id=hit.primary_key.to_s.to_sym
        fr=highlight.format { |word| "<result>#{word}</result>" }
        @results.merge!(id => ["description",fr])
    end
    hit.highlights(:notes).each do |highlight|
        id=hit.primary_key.to_s.to_sym
        fr=highlight.format { |word| "<result>#{word}</result>" }
        @results.merge!(id => ["notes",fr])
    end
end

and on the view, wherever I want to render any value of those, I do the following:

<% @entries.each do |f| %>
    <% j=f[:id].to_s.to_sym %>
    <% if !@results[j].nil? && @results[j][0]=="description" %>
        <%= @results[j][1].html_safe %>
    <% else  %>
        <%= f[:description] %>
    <% end %>
[...] (likewise for notes)
<% end %>

Please, note I created a css definition for <result> markup to make the text notable.

like image 187
Ruby Racer Avatar answered Nov 15 '22 06:11

Ruby Racer


Code looks good to me for highlighting the first matching word in the title, since I have similar code. Have you tried rebuilding your solr index and restarting the servers?

Also, can you try reverting your solrconfig.xml to its default values? Someone had a similar problem after modifying solrconfig.xml, Ref https://groups.google.com/forum/#!searchin/ruby-sunspot/highlight/ruby-sunspot/kHq0Dw35UWs/ANIUwERArTQJ

If you want to override the highlighting option in solrconfig.xml, search for max_snippets on this site http://outoftime.github.io/ . You may want to try options like

highlight :title, :max_snippets => 3, :fragment_size => 0  # 0 is infinite
like image 30
konyak Avatar answered Nov 15 '22 05:11

konyak