我怎样才能使这部续集表达更加精彩

时间:2013-07-30 11:17:28

标签: ruby sequel

我有以下表达式:

  result = where(
    Sequel.like(Sequel.function(:lower, Sequel.join([:first_name, :last_name], ' ')), "%#{query.name.downcase}%") |
      Sequel.like(Sequel.function(:lower, :email), "%#{query.name.downcase}%")
  )

有没有办法可以告诉续集在多列上运行相同的表达式?

2 个答案:

答案 0 :(得分:0)

你可以使用

的内容
columns.map{|c| "c LIKE '%<someVar>%'}.join("AND ")

这将创建一个LIKE,并列出您需要的所有列。例如

columns = ["age", "gender", "hair_colour"]
columns.map{|c| "c LIKE '%<someVar>%'}.join("AND ")

#=> age LIKE '%<someVar%' AND gender LIKE '%<someVar>%' AND hair_colour LIKE '%<someVar>%'

填充方式取决于代码的其余部分是如何构建的,但这是适合它的框架。

另一种方法是使用类似的数组映射方法,但在地图中使用where()。延迟调用将允许您在运行查询之前迭代任何条件。这解决了@the Tin Man提到的潜在不满

答案 1 :(得分:0)

这就是我要做的事情:

首先,查找电子邮件地址和用户名字段等数据应该是 在数据库中标准化为小写。这大大简化了编码。

如果您需要维护原始案例,例如用户的第一个和最后一个案例 显示名称,将它们保存为单独的名字和姓氏字段,然后创建 一个单独的字段,它们已经加入并进行散列搜索,并在您查看该字段时在代码中使用相同的哈希值。如果将其编入索引,与使用like搜索相比,它的查找速度非常快。

这是使用纯Sequel以编程方式生成where的代码,而不是生成SQL partial并将其注入到查询中。请注意,Sequel知道SQLite的语法,并自动创建一个有效的where子句。如果您要连接到Segre支持的PostgreSQL,MySQL,Oracle,MSSQL,Sybase或其他DBM,则同样适用;您不必调整代码只是为了使其工作,您只需调整DSN告诉Sequel使用哪个驱动程序以及DB凭据是什么。

构建测试数据库:

require 'sequel'

DB = Sequel.sqlite
DB.create_table :items do
  primary_key :id
  String :first_name
  String :last_name
  String :email
  String :attr1, :default => 'attr'
  String :attr2, :default => 'attr'
end

items = DB[:items]
%w[Jane Jim John Junior].each do |fn|
  items.insert(:first_name => fn, :last_name => 'Doe', :email => fn.downcase + 'doe@email.com')
end
puts items.all

我们走了......:

user_name = '%' + 'John Doe'.downcase + '%'
query = DB[:items].where(
  Sequel.ilike(
    Sequel.join([:first_name, :last_name], ' '),
    user_name
  )
)

columns = [:email, :attr1, :attr2]
columns.each do |col|
  query = query.or(
    Sequel.ilike(
      col,
      user_name.delete(' ')
    )
  )
end

puts query.sql

puts query.first

运行代码输出表的内容:

{:id=>1, :first_name=>"Jane", :last_name=>"Doe", :email=>"janedoe@email.com", :attr1=>"attr", :attr2=>"attr"}
{:id=>2, :first_name=>"Jim", :last_name=>"Doe", :email=>"jimdoe@email.com", :attr1=>"attr", :attr2=>"attr"}
{:id=>3, :first_name=>"John", :last_name=>"Doe", :email=>"johndoe@email.com", :attr1=>"attr", :attr2=>"attr"}
{:id=>4, :first_name=>"Junior", :last_name=>"Doe", :email=>"juniordoe@email.com", :attr1=>"attr", :attr2=>"attr"}

为查询DB而生成的SQL:

SELECT * FROM `items` WHERE ((UPPER((`first_name` || ' ' || `last_name`)) LIKE UPPER('%john doe%') ESCAPE '\') OR (UPPER(`email`) LIKE UPPER('%johndoe%') ESCAPE '\') OR (UPPER(`attr1`) LIKE UPPER('%johndoe%') ESCAPE '\') OR (UPPER(`attr2`) LIKE UPPER('%johndoe%') ESCAPE '\'))

为便于阅读而格式化:

SELECT * FROM `items`
WHERE (
  (UPPER((`first_name` || ' ' || `last_name`)) LIKE UPPER('%john doe%') ESCAPE '\') OR
  (UPPER(`email`) LIKE UPPER('%johndoe%') ESCAPE '\') OR
  (UPPER(`attr1`) LIKE UPPER('%johndoe%') ESCAPE '\') OR
  (UPPER(`attr2`) LIKE UPPER('%johndoe%') ESCAPE '\')
)

查询后的结果行:

{:id=>3, :first_name=>"John", :last_name=>"Doe", :email=>"johndoe@email.com", :attr1=>"attr", :attr2=>"attr"}

这不是最干的代码,但作为一个例子,它得到了重点。