Search code examples
rubyhashsearchkick

Building a dynamic query with separate hashes


Ok, I've been trying to figure out how to approach this all morning. Let's say you have a hash that looks like this:

{"luxury_shopper"=>"10", "movie_goer"=>"80"}

and you want to build a query that looks like this:

Observation.search("something", boost_by: {biz_trv:{factor: 10}} && {day_com:{factor:100}})

My approach so far is to convert the incoming hash to look like this:

[{:luxury_shopper=>{:factor=>"10"}}, {:movie_goer=>{:factor=>"80"}}]

by iterating over the original hash like this:

params[:filter].map {|k,v| {k.to_sym => {factor:v}}}

The problem I'm having is that since the query I'm trying to build is made up of an unknown number of hashes that I will "boost_by", I can't just do something like filters[0] && filters[1] I'm stumped here. Does anyone know how I could dynamically insert hashes into my query and place the operator between them?

EDIT:

The query looks like this:

Observation.search("someting", boost_by: `insert hash` `insert operator` `insert hash` etc...)

The above query could have any number of hashes and operators. So if a user wanted to pass in 10 fields to boost_by, I need to be able to accept all 10 of those hashes and whatever operator goes between them, so for example, my query could look like either of the below examples:

Observation.search("something", boost_by: {biz_trv:{factor: 10}})

Observation.search("something", boost_by: {biz_trv:{factor: 12}} && {day_com:{factor:50}} && {location:{factor:40}})

Solution

  • i have a solution that involves forming a string of your query, and then using the #send method to deliver your query string to the object.

    hash = {"luxury_shopper"=>"10", "movie_goer"=>"80"}
    BLANK_PARAMS = "boost_by: "
    params = BLANK_PARAMS
    hash.each do |k, v|
      if params == BLANK_PARAMS
        params += "{#{k}: {factor: #{v}}}"
      else
        params += " && {#{k}: {factor: #{v}}}"
      end
    end
    

    at the end of this operation, the params string will be the following:

    "boost_by: {luxury_shopper: {factor: 10}} && {movie_goer: { factor: 80}}"
    

    so if you now wanted to run the following command:

    Observation.search("something", boost_by: {luxury_shopper: {factor: 10}} && {movie_goer: {factor: 80}})
    

    you could do so using #send as such:

    Observation.send('search', 'something', params)