Search code examples
ruby-on-railssearchkick

How to use `Searchkick.multi_search` along with `with_highlights`? undefined method `with_highlights'


We're trying to optimize our search requests by making a single bulk search, so we're trying to use Searchkick.multi_search. However, it only returns Searchkick::Query with the results populated in a results attribute, as a regular Array.

Then, now if I try results.with_highlights... it fails with

undefined method `with_highlights' for #<Array:0x000055a82a7440f0>

Or if I try on the search_query.with_highlights it fails with

undefined method `with_highlights' for #<Searchkick::Query:0x00007f47c5d0cde8>

How can I get the highlights when using multi_search?


Solution

  • Updated Answer for Searchkick 4.6.1+

    Talked to Ankane from Searchkick here https://github.com/ankane/searchkick/pull/1518. He ended up releasing a new version with fixes to this then the original answer here is only valid up to Searchkick version 4.6.0.

    For 4.6.1+ just do:

      groups = Group.search(query, execute: false)
      users = User.search(query, execute: false)
    
      Searchkick.multi_search([groups, users])
    
      highlighted_groups_results = groups.with_highlights(...
      ...
    

    Original answer for 4.6.0-

    Got it!

    After diving into the Searchkick codebase and checking the Searchkick::Query implementation, discovered that the execute method is what I need.

    def execute
        @execute ||= begin
                         begin
                           response = execute_search
                           if retry_misspellings?(response)
                             prepare
                             response = execute_search
                           end
                         rescue => e # TODO rescue type
                           handle_error(e)
                         end
                         handle_response(response)
                       end
    end
    

    https://github.com/ankane/searchkick/blob/230ec8eb996ae93af4dc7686e02555d995ba1870/lib/searchkick/query.rb#L101

    handle_response(response) is exactly what we need for making with_highlights work.

    Then my final implementation ended up being something like the following:

    groups = Group.search(query, execute: false)
    users = User.search(query, execute: false)
    
    Searchkick.multi_search([groups, users])
    
    # execute here won't do any additional requests as it's already cached in an instance variable @execute
    highlighted_groups_results = groups.execute.with_highlights(...
    ...