使用单独的哈希构建动态查询

时间:2015-05-27 16:15:11

标签: ruby hash searchkick

好的,我一直试图弄清楚如何在整个上午处理这个问题。假设您有一个如下所示的哈希:

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

并且您想构建一个如下所示的查询:

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

到目前为止,我的方法是将传入的哈希转换为如下所示:

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

迭代原始哈希,如下所示:

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

我遇到的问题是,由于我正在尝试构建的查询由未知数量的哈希组成,我将“boost_by”,我不能只做像filters[0] && filters[1]这样的事情我我在这里难过。有谁知道如何动态地将哈希插入到我的查询中并将运算符放在它们之间?

编辑:

查询如下所示:

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

上述查询可以包含任意数量的哈希值和运算符。因此,如果用户想要将10个字段传递给boost_by,我需要能够接受所有10个哈希以及它们之间的任何操作符,因此,例如,我的查询可能看起来像以下任一示例:

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}})

3 个答案:

答案 0 :(得分:2)

我有一个解决方案,包括形成一个查询字符串,然后使用#send方法将查询字符串传递给对象。

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

在此操作结束时,params字符串将如下:

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

所以如果您现在想要运行以下命令:

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

你可以这样使用#send:

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

答案 1 :(得分:1)

我不确定是否正确理解了您的问题,但如果您需要在任意数量的元素之间应用&&,则可以使用Enumerable#all?方法,例如

filters = [{biz_trv:{factor: 10}}, {day_com:{factor:100}}, …]
Observation.search("something", boost_by: filters.all?)

更新

filters = [{biz_trv:{factor: 12}}, {day_com:{factor:50}},
           {location:{factor:40}}]
Observation.search("something",
                   boost_by: filters.inject {|ac,e| ac && e})

答案 2 :(得分:0)

假设您总是想要使用相同的运算符,您希望将map的输出传递给行为类似于inject的内容:

(params[:filter].map {|k,v| {k.to_sym => {factor:v}}}).inject() { |r,c| r && c }

注意:未经测试!