2010-03-25 109 views
11

在這裏發佈一個關於如何提高我的SQL搜索方法的速度的問題之後,我被建議更新我的表以利用全文搜索。這就是我現在所做的,使用Gist索引來加快搜索速度。在一些「簡單」的查詢中,我注意到了一個顯着的增加,我很高興。PostgreSQL:全文搜索 - 如何搜索部分單詞?

但是,我很難搜索部分單詞。例如,我有幾個包含Squire(454)的記錄,而且我有幾個包含Squirrel(173)的記錄。現在,如果我搜索Squire,它只會返回454條記錄,但我也希望它可以返回Squirrel記錄。

我的查詢看起來像這樣

SELECT title 
FROM movies 
WHERE vectors @@ to_tsoquery('squire'); 

我想我能做到to_tsquery('squire%'),但不起作用。
如何獲得它以搜索部分匹配?

此外,在我的數據庫中,我有記錄是電影和其他只是電視節目。這些名稱與名稱不同,因此「明斯特」是電視節目,而明斯特是該節目的電影。我想要做的就是隻搜索電視節目和電影。有關我如何實現這一點的任何想法?

問候 Anthoni

+0

如果你有'squire'這個搜索鍵,但是想得到'squirrel'的結果,你可能需要指定其他的約束條件。因爲否則的話,人們可能會說他們有搜索鍵「媽媽」,但想要結果「兔子」。所以也許你可能想要分割你的搜索鍵並把'squire'變成'|' sq | squ | squi | squir |鄉紳......這個或更有趣的算法會讓你成爲'松鼠'。我認爲@Joshua Burns的答案包含比我更通用的解決方案,但如果你想要通用。 – 2015-09-17 08:12:46

回答

4

即使使用LIKE你將無法從squire%得到「松鼠」,因爲「松鼠」有兩個「R的。要獲得鄉紳和松鼠,你可以運行下面的查詢:

SELECT title FROM movies WHERE vectors @@ to_tsquery('squire|squirrel'); 

電影和電視之間的區別展示了應該列添加到您的數據庫。但是,這種貓的皮膚有很多種方法。您可以使用子查詢來強制postgres首先找到匹配'squire'和'squirrel'的電影,然後搜索該子集以查找以'''開頭的標題。可以創建索引以便在LIKE '"%...'搜索中使用。

SELECT title 
FROM (
    SELECT * 
    FROM movies 
    WHERE vectors @@ to_tsquery('squire|squirrel') 
) t 
WHERE title ILIKE '"%'; 

可能工作
SELECT title 
FROM movies 
WHERE vectors @@ to_tsquery('squire|squirrel') 
    AND title ILIKE '"%'; 
0

一件事是打破了一句話:圍繞與他們亂找這是最快的 -

不考察其他索引可能你也可以運行這些你正在尋找更小的p藝術。所以,你可以尋找那些擁有squi或quir或者鄉紳等等的東西......我不確定它的效率如何,但它可能會有所幫助。

當您搜索電影或電影時,您可以嘗試將文本放在單引號中。所以它可以是'show'或者'show''。我認爲這也可以發揮作用。

27

嘗試,

SELECT title FROM movies WHERE to_tsvector(title) @@ to_tsquery('squire:*') 

這適用於PostgreSQL的8。4+

+2

你已經指定了一個前綴匹配的詞位,但它不會解決問題:它仍然缺少'r'。你應該刪掉這個答案。 – 2013-02-11 00:10:10

+2

@RichardMichael我不同意,因爲這種方法的作品。 OP正試圖獲得兩個不相似的單詞。 「鄉紳」不是**「松鼠」一詞的一部分。他要求部分匹配,這個答案就是這樣。它應該是upvoted。 – 2016-09-06 08:27:04

+0

感謝您的支持,我在一個用例中提供幫助。 +1 – 2017-11-23 04:48:59

25

Anthoni,

假設你打算只使用ASCII編碼(可能是困難的,我知道),一個非常可行的辦法可能是巽(pg_trgm)模塊:http://www.postgresql.org/docs/9.0/interactive/pgtrgm.html

八卦利用Gist和Gin等內置索引方法。您必須進行的唯一修改是在定義索引時指定gist_trgm_opsgin_trgm_ops的運營商類別。

如果尚未安裝的contrib模塊,在Ubuntu它一樣方便,運行在shell下面的命令:

# sudo apt-get install postgresql-contrib 

於contrib模塊之後可用,您必須安裝pg_trgm拓成有問題的數據庫。您可以通過在數據庫上執行下面的PostgreSQL的查詢您希望將模塊安裝到這樣做:在pg_trgm延長已安裝

CREATE EXTENSION pg_trgm; 

後,我們準備有一番情趣!

-- Create a test table. 
CREATE TABLE test (my_column text) 
-- Create a Trigram index. 
CREATE INDEX test_my_colun_trgm_idx ON test USING gist (my_column gist_trgm_ops); 
-- Add a couple records 
INSERT INTO test (my_Column) VALUES ('First Entry'), ('Second Entry'), ('Third Entry') 
-- Query using our new index -- 
SELECT my_column, similarity(my_column, 'Frist Entry') AS similarity FROM test WHERE my_column % 'Frist Entry' ORDER BY similarity DESC 
+2

爲什麼這不是公認的答案?是最好的:) – jperelli 2012-05-06 21:31:26

+0

在你的例子中的相似性使用完美的單詞,而不是你的where子句中使用的拼寫錯誤的單詞。選擇相似性('Frist Entry','First Entry')=> 0.5 – 2012-11-27 10:39:42

+0

好點,我的錯字。解決。感謝您的領導:) – 2012-11-29 16:34:12

4

@ alexander-mera解決方案效果很好!

注意:也請務必將空格轉換爲+。例如,如果您正在搜索squire knight

SELECT title FROM movies WHERE to_tsvector(title) @@ to_tsquery('squire+knight:*') 
+0

使用'+'不適用於PosgreSQL 9.4.1。如果我使用'&',就像魅力一樣。 – facundofarias 2015-10-27 10:15:33

0

的廣泛的解決方案是使用PG的ts_rewrite功能設置一個別名錶,對於交替匹配(見Query Rewriting)的工作原理。這包括像上面,而你也處理完全不同的情況下,像在那個鏈接搜索tree rat並獲得結果squirrel

全部細節和解釋的情況下,但它的要點是,你可以設置一個別名錶2 ts_query列,並通過該表的查詢與您的搜索,例如:

WHERE vectors @@ ts_rewrite(to_tsquery('supernovae & crab'), 'SELECT * FROM aliases') 

這是類似的:

CREATE TABLE aliases (t tsquery primary key, s tsquery); 
INSERT INTO aliases VALUES(to_tsquery('supernovae'), to_tsquery('supernovae|sn')); 

SELECT ts_rewrite(to_tsquery('supernovae & crab'), 'SELECT * FROM aliases'); 

在這看起來更像是一個最終查詢所得到PG中的詞庫設置,但每次添加內容時都不需要完全重新索引。正如你遇到的一些拼寫變化和「當我搜索這個我期待這樣的結果」的情況下,只需將它們快速添加到表格中就很容易。只要基於ts_rewrite的查詢返回了預期的2列to_tsquery列,您就可以向該表中添加更多列。

當您深入瞭解該文檔時,您還會看到有關性能調整的建議示例。在使用trigram進行純速度和使用向量/查詢/重寫進行魯棒性之間有一個平衡點。