0

我有以下表达式:

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

有没有办法告诉sequel对多列运行相同的表达式?

4

2 回答 2

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 提到的潜在不满

于 2013-07-30T12:51:34.910 回答
0

这是我要做的:

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

如果您需要维护原始大小写,例如用于显示用户的名字和姓氏,请将它们保留为单独的名字和姓氏字段,并创建一个单独的字段,其中它们已经连接和散列以进行搜索,并使用当您查看该字段时,您的代码中的哈希值相同。如果将其编入索引,那么与使用搜索相比,查找速度会非常快like

这是以编程方式生成where使用纯 Sequel 的代码,而不是生成 SQL 部分并将其注入到您的查询中。请注意,Sequel 知道 SQLite 的语法,并自动创建一个有效的 where 子句。如果您要连接到 PostgreSQL、MySQL、Oracle、MSSQL、Sybase 或 Sequel 支持的其他 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"}

为查询数据库而生成的 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"}

这不是最 DRY 的代码,但举个例子,它就明白了。

于 2013-07-30T15:44:46.867 回答