2012-08-22 43 views
0

我的用户模型有:轨 - 跨越两个领域的结合搜索各种配套

用户(ID,FNAME,LNAME)

我需要一个查询按名称搜索用户。我有本使用:

@users = User.find(:all, 
         :select => 'users.*', 
         :conditions => ["fname || ' ' || lname LIKE ?", '%'+"James Bond"+'%'] 
        ) 

如果你搜索詹姆斯,用户(詹姆斯·邦德)返回,但如果搜索返回“邦德”没什么。我如何更新此查询以通过fname,lname或fname和lname返回用户?

感谢

回答

1

我不知道你是怎么RoR中指定,但在PostgreSQL的水平,这听起来像你可能需要使用卦搜索。如果您使用的是PostgreSQL 9.1或更高版本,则可以将它与“K最近邻居”(KNN)搜索结合使用,直接返回K个最佳匹配。这通常比其他名称的“模糊”搜索技术快几个数量级。

要安装三元支持,如果你有你的机器类型的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,则将以“最佳匹配”顺序从索引返回行。