这是我要做的:
首先,用于查找的电子邮件地址和用户名字段等数据应在数据库中标准化为小写。这大大简化了您的编码。
如果您需要维护原始大小写,例如用于显示用户的名字和姓氏,请将它们保留为单独的名字和姓氏字段,并创建一个单独的字段,其中它们已经连接和散列以进行搜索,并使用当您查看该字段时,您的代码中的哈希值相同。如果将其编入索引,那么与使用搜索相比,查找速度会非常快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 的代码,但举个例子,它就明白了。