我的用户模型有:
用户(id,fname,lname)
我需要一个查询来按名称搜索用户。我曾经使用过:
@users = User.find( :all,
:select => 'users.*',
:conditions => ["fname || ' ' || lname LIKE ?", '%'+"James Bond"+'%']
)
如果您搜索James,则返回用户(James Bond),但如果您搜索“Bond”,则不会返回任何内容。如何更新此查询以通过fname,lname或fname和lname?
返回用户由于
答案 0 :(得分:1)
我不知道你如何在RoR中指定它,但在PostgreSQL级别,听起来你可能想要使用trigram搜索。如果您使用的是PostgreSQL 9.1或更高版本,则可以将其与“K最近邻”(KNN)搜索结合使用,以直接返回K个最佳匹配。对于名称,这通常比其他“模糊”搜索技术快几个数量级。
要安装trigram支持,如果您的计算机上有contrib模块,请键入:
CREATE EXTENSION pg_trgm;
假设两个名称字段都是NOT NULL
(只是为了避免使用COALESCE
谓词混淆答案),可以使用以下命令创建索引:
CREATE INDEX users_name ON users USING gist
((fname || ' ' || lname) gist_trgm_ops);
这是有趣的部分,您可以在几毫秒内找到数百万条记录的近似匹配:
SELECT *
FROM users
ORDER BY (fname || ' ' || lname) <-> 'James Bond'
LIMIT 10;
<->
运算符是“距离”运算符。如果将ORDER BY
子句用于使用gist_trgm_ops
和定义的索引,则使用LIMIT
,将在“最佳匹配”中从索引返回行“序列。