如何通过最接近的查询来查询结果?

时间:2014-03-16 10:36:44

标签: ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-4 jquery-tokeninput

我有一个字段,我正在使用Jquery TokenInput来自动填充产品。找到我正在做的产品:

def token
   @products = Product.order(:name)
   respond_to do |format|
     format.html
     format.json { render json: @products.where("name ILIKE ?", "%#{params[:q]}%").limit(10).order('name DESC') }
   end
end

如果我有一个名为Rice的产品并在该字段上搜索,输入“r”,“ri”和“ric”,我希望最接近的结果是与查询匹配的结果。相反,如果我在数据库中有超过10种不同类型的Rice,结果将“无序”,其中Rice被放置在10个已建立的大米中的第6或第9位。对我来说,赖斯应该先来,而不是米饭球或蛋糕,但我会得到类似的东西:

Brown Rice # First result in Tokeninput
Rice Cake
Yellow Rice
Long Grain Rice
Rice Ball
Chinese Rice
Super Rice
Rice
New Rice
The Super Rice Game

即使我输入“Rice”,我也会得到类似于上面的内容。我希望它是第一个选择,如果键入r, ri, ric or rice但我的结果不相信顺序,他们只想要混乱。怎么会这样做?

4 个答案:

答案 0 :(得分:2)

您可以将以下方法添加到Product模型中:

def self.good_search(criteria)
  regexp = /#{criteria}/i; # case-insensitive regexp based on your string

  result = order(:name).where("name ILIKE ?", "%#{criteria}%").limit(10)
  result.sort{|x, y| (x =~ regexp) <=> (y =~ regexp) } 
end

这里我使用匹配运算符(=~)返回regexp匹配的位置。早期的大米&#34;遇到了越接近结果数组字符串的顶部&#39; ll。 这种方法可能不适合大数组,但对于10个元素,它没问题。

这是你的控制者:

def token
  respond_to do |format|
    format.html
    format.json { render json: Product.good_search(params[:q]) }
  end
end
祝你好运!

答案 1 :(得分:2)

全文搜索

我们做过类似的事情 - 你正在寻找full text search

我们已经做了类似于你在http://firststopcosmeticshop.co.uk寻求的事情 - 我们这样做的方式是这样的:

#config/routes.rb
match 'search(/:search)', :to => 'products#search', :as => :search, via: [:get, :post]

#app/controllers/products_controller.rb
def search      
    @products = Product.search(params[:search])
    respond_to do |format|
        format.js   { render :partial => "elements/livesearch", :locals => {:search => @products, :query => params[:search]} }
        format.html { render :index }
    end
end

#app/models/product.rb
def self.search(search)
 basic_search(name: search, description: search).take(5) #-> uses textacular gem
end

这为PGSQL使用textactular gem,但希望能给你一些关于如何加载执行搜索的想法


<强>代码

对于您,我建议您执行以下搜索:

def token
   @products = Product.where(name: "%#{params[:q]}%").order(name: :desc)
   respond_to do |format|
     format.html
     format.json { render json: @products.to_json }
   end
end

虽然这不会直接回答你的问题,但我希望它会给你一些关于效率的信息

答案 2 :(得分:2)

我使用此查询解决了我的搜索问题,我认为您也可以使用它并使搜索结果更好。给定一个query字符串作为输入我使用了以下sql:

select items.*
from items
where lower(items.name) like 'query%' or items.name like '% query%'
order by case when lower(items.name) like 'query%' then 1 else 2 end,
items.name ASC

这将返回所有项目,这些项目至少有一项与订购结果匹配的作品与首先开始比赛的作品相匹配。

在Rails中,这将是:

Item.where("lower(items.name) like '#{downcase_query}%' or 
            lower(items.name) like '% #{downcase_query}%'").
     order("case when lower(items.name) like '#{downcase_query}%' then 1 else 2 end, 
            items.name ASC")

答案 3 :(得分:0)

一般来说,使用.sort或.sort_by

排序的红宝石关键是

例如,一个例子就是:

%w {banana apple pear fig} .sort_by {| word | word.length}#=&gt; [“fig”,“pear”,“apple”,“banana”]

现在在您的示例中,您需要指定要使用的标准。

鉴于你想首先返回Rice,然后是Rice Ball,我建议添加一个首选返回Rice的排序方法,然后处理其余的结果。