2012-08-22 67 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,則將以「最佳匹配」順序從索引返回行。