Search code examples
ruby-on-railsrubyelasticsearchtire

What are the parameters for the search method of the Tire gem?


I need to run a search using Tire with my query specifically defined as a parameter, but I'm unsure how to proceed.

search = {
  query: {
    function_score: {
      query: { match_all: {} },
      # filters is an array previously built
      functions: filters,
      score_mode: "total"
    }
  }
}

Program.tire.search(load: true, size: 50, search)

I'm receiving the following error: /Users/app/models/program_match.rb:122: syntax error, unexpected ')', expecting tASSOC which makes me believe I'm simply missing a key word before I call search.

Any help would be greatly appreciated!


Solution

  • You probably just need to do:

    Program.tire.search({load: true, size: 50}.merge(search))
    

    EDIT

    Actually, looking at the source for search (https://github.com/karmi/retire/blob/master/lib/tire/model/search.rb), it looks like you need to do:

    Program.tire.search(search, {load: true, size: 50})
    

    search expects two params (query, options) or one param (for options) and a block (for the query). Ruby gets confused because you have started a hash (load: true ...) and then just put a new hash (your search hash), which it sees as a hash key (with no value).

    Also, if you are just starting out with Tire, I would suggest checking out elasticsearch-rails, which, according to the author, is replacing Tire.

    I recently converted a Tire project to elasticsearch-rails, and have found that it can do everything Tire does, although it doesn't provide the query DSL (it seems like you're not using that anyway, so no loss).

    EDIT 2

    You can do a simple match_all query like:

    Program.tire.search(load: true, size: 50) { query { all } }
    

    You can get something similar by doing:

    Program.tire.search('*', load: true, size: 50)
    

    As I noted in a comment below, a query as the first param for search will always be wrapped in a query_string query.

    Probably the best way to do what you asked initially is to do:

    Tire.search(Video.tire.index_name, query: {
      function_score: {
        query: { match_all: {} },
        functions: filters,
        score_mode: "total"
      }
    }).results
    

    I just tested a similar function_score query on a local project and confirmed that it produces the expected query.

    EDIT 3

    I've never used the load option before, but it looks like you can do:

    Tire.search(Video.tire.index_name, payload: {
      query: {
        function_score: {
          query: { match_all: {} },
          functions: filters,
          score_mode: "total"
        }
      }
    }, load: true).results
    

    Note that you have to wrap the query as the value for payload.