我想用Ruby和Sequel做一个自动完成

时间:2013-06-14 11:20:40

标签: ruby postgresql sequel

我正在使用续集与prostgres和Sinatra。我想做一个自动完成搜索。我已经验证了我发送GET的jQuery工作正常。

Ruby代码是:

get '/search' do
  search = params[:search]
  DB[:candidates].select(:last).where('last LIKE ?', '_a_').each do |row|
    l = row[:last] 
  end
end

问题是续集查询:

我已经尝试了所有可能的查询配置,我可以想到没有运气。

因此,例如,在上面的查询中,我得到所有姓氏中都有“a”的人,但是当我将查询更改为:

DB[:candidates].select(:last).where('last LIKE ?', 'search')

DB[:candidates].select(:last).where('last LIKE ?', search)  # (without '')

我一无所获。

我已完成warn params.inspect,表示正在传递参数搜索,所以我被卡住了。

任何想法应该如何编写查询?

最后,结果问题的第二部分(当它与'_a_'一起使用时)呈现为{:last=>"Yao"}我想要姚明,我该怎么做?

我尝试了很多不同类型的查询,包括原始SQL,但没有运气。或者这种方法是否完全错误?

2 个答案:

答案 0 :(得分:1)

刚刚安装了Sequel并做了一个工作示例:

require "rubygems"
require "sequel"

# connect to an in-memory database
DB = Sequel.sqlite

# create an items table
DB.create_table :items do
  primary_key :id
  String :name
  Float :price
end

# create a dataset from the items table
items = DB[:items]

# populate the table
items.insert(:name => 'abc', :price => rand * 100)
items.insert(:name => 'def', :price => rand * 100)
items.insert(:name => 'ghi', :price => rand * 100)
items.insert(:name => 'gui', :price => rand * 100)

# print out the number of records
puts "Item count: #{items.count}"

# print out the average price
puts "The average price is: #{items.avg(:price)}"

recs = items.select(:name).where(Sequel.like(:name, 'g%'))
recs.each do |rec|
  puts rec.values
end

我想你会明白这一点。

已更新

所以在你的情况下你应该试试这个:

DB[:candidates]
   .select(:last)
   .where(Sequel.like(:last, "#{search}%"))
   .map{|rec| rec.values}.flatten

它应该返回找到的字符串数组。

答案 1 :(得分:0)

the Sequel documentation复制/粘贴:

  

您可以使用Sequel.like方法以区分大小写的方式搜索SQL字符串:

items.where(Sequel.like(:name, 'Acme%')).sql
#=> "SELECT * FROM items WHERE (name LIKE 'Acme%')"
     

您可以使用Sequel.ilike方法以不区分大小写的方式搜索SQL字符串:

items.where(Sequel.ilike(:name, 'Acme%')).sql
#=> "SELECT * FROM items WHERE (name ILIKE 'Acme%')"
     

您可以将Regexp指定为类似的参数,但这可能仅适用于PostgreSQL和MySQL:

items.where(Sequel.like(:name, /Acme.*/)).sql
#=> "SELECT * FROM items WHERE (name ~ 'Acme.*')"
     

喜欢也可以采取多个论点:

items.where(Sequel.like(:name, 'Acme%', /Beta.*/)).sql
#=> "SELECT * FROM items WHERE ((name LIKE 'Acme%') OR (name ~ 'Beta.*'))"

Open up a Sequel console(不是您的Sinatra应用)并使用查询,直到您获得结果。由于您说您只想要last列,因此您的查询应该是:

# Search anywhere inside the last name
DB[:candidates].where( Sequel.ilike(:last, "%#{search}%") ).select_map(:last)

# Find last names starting with the search string
DB[:candidates].where( Sequel.ilike(:last, "#{search}%") ).select_map(:last)

Uglier替代方案:

DB[:candidates]
  .select(:last)
  .where( Sequel.ilike(:last, "%#{search}%") )
  .all
  .map{ |hash| hash[:last] }

DB[:candidates]
  .select(:last)
  .where( Sequel.ilike(:last, "%#{search}%") )
  .map( :last )

如果您想按最佳匹配对搜索结果进行排名,可能对我的免费LiqrrdMetal library感兴趣。您可以将所有姓氏的完整列表提取到Ruby中,然后使用LiqrrdMetal搜索它们,而不是搜索数据库。这将允许“pho”的搜索字符串匹配“Phong”和“Phrogz”,前者的得分在排名中更高。