2011-05-27 135 views
6

我正在尋找一種方法來在PostgreSQL中使用tsvector來模擬SELECT * FROM table WHERE attr LIKE '%text%'之類的內容。使用全文搜索匹配以前綴結尾的短語

我已經創建了tsvector屬性而不使用字典。現在,查詢像...

SELECT title 
FROM table 
WHERE title_tsv @@ plainto_tsquery('ph:*'); 

...返回所有的遊戲,比如「物理」,「PHP」,等等,但我怎樣才能創建一個返回所有記錄中,其中冠軍開始查詢「 Zend Fram'(它應該返回例如'Zend Framework')?

當然,我可以使用類似:

SELECT title 
FROM table 
WHERE title_tsv @@ to_tsquery('zend') 
AND title_tsv @@ to_tsquery('fram:*'); 

然而,這似乎有點尷尬。

所以,問題是:有沒有辦法制定上述使用類似給出的查詢:

SELECT title 
FROM table 
WHERE title_tsv @@ to_tsquery('zend fram:*'); 

回答

5
SELECT title 
FROM table 
WHERE title_tsv @@ to_tsquery('zend') and 
title_tsv @@ to_tsquery('fram:*') 

等同於:

SELECT title 
FROM table 
WHERE title_tsv @@ to_tsquery('zend & fram:*') 

當然是發現的「Zend也沒有框架」。

你當然可以表達了對冠軍的tsquery賽後正則表達式匹配,但你將不得不使用EXPLAIN分析,以確保tsquery,而不是之前之後正在執行。

2

有一個辦法做到這一點Postgres裏使用trigrams和杜松子酒/要點索引。有一個簡單的例子,但有一些粗糙的邊緣,在Kristo Kaiv的這篇文章中:Substring Search

1

不漂亮的解決方案,但它應該做的工作:

psql=# SELECT regexp_replace(cast(plainto_tsquery('Zend Fram') as text), E'(\'\\w+\')', E'\\1:*', 'g') ; 
    regexp_replace  
--------------------- 
'zend':* & 'fram':* 
(1 row) 

它可以用於像:

psql=# SELECT title FROM table WHERE title_tsv(title) @@ to_tsquery(regexp_replace(cast(plainto_tsquery('Zend Fram') as text), E'(\'\\w+\')', E'\\1:*', 'g')); 

如何工作的:

  1. 蒙上平原tsquery字符串:cast(plainto_tsquery('Zend Fram') as text)
  2. 使用正則表達式來追加:*前綴匹配到每一個搜索詞:regexp_replace(..., E'(\'\\w+\')', E'\\1:*', 'g')
  3. 將其轉換回非純tsquery。 to_tsquery(...)
  4. ,並用它在搜索表達式SELECT title FROM table WHERE title_tsv(title) @@ ...
2

的Postgres 9.6介紹了全文搜索短語搜索功能。所以,這個工程現在:

SELECT title 
FROM tbl 
WHERE title_tsv @@ to_tsquery('zend <-> fram:*');

<-> being the FOLLOWED BY operator.

它發現'富Zend框架欄''的Zend框架',但'富Zend的無邊框條'

引述release notes for Postgres 9.6:

的短語的搜索查詢可以在tsquery輸入使用新 運營<-><N>指定。前者意味着之前和之後的詞位必須以該順序彼此相鄰。後者 表示它們必須完全相同N詞位分開。

爲了獲得最佳的性能支持的查詢與GIN指數:

CREATE INDEX tbl_title_tsv_idx ON tbl USING GIN (title_tsv); 

或者在表中的所有(腹脹它和複雜寫入)不存儲title_tsv。您可以使用表達式指數來代替:

CREATE INDEX tbl_title_tsv_idx ON tbl USING GIN (to_tsvector('english', title)); 

您需要指定文本搜索配置(通常是特定語言),使表情不變。並相應地調整查詢:

... 
WHERE to_tsvector('english', title) @@ to_tsquery('english', 'zend <-> fram:*');