Postgresql
從 GIN 索引的 TSVECTOR 列中獲取部分匹配
我想通過查詢得到結果:
SELECT * FROM ( SELECT id, subject FROM mailboxes WHERE tsv @@ plainto_tsquery('avail') ) AS t1 ORDER by id DESC;
這有效並返回
tsv
包含的行Available
。但是如果我使用avai
(droppedlable
) 它什麼也找不到。所有查詢都必須在字典中嗎?我們不能只查詢這些字母嗎?我有一個包含電子郵件正文(內容)的數據庫,我想讓它隨著它每秒的增長而快速增長。目前我正在使用
... WHERE content ~* 'letters`
所有查詢都必須在字典中嗎?
不,因為只有詞幹(根據使用的文本搜尋配置)在索引中開始。但更重要的是:
這會起作用:
SELECT id, subject FROM mailboxes WHERE tsv @@ **to_tsquery**(**'simple'**, 'avail**:*'**) ORDER BY id DESC;
注意3點:
- 在這種情況下使用
to_tsquery()
, notplainto_tsquery()
,因為(引用手冊):…
plainto_tsquery
將無法辨識tsquery
其輸入中的運算符、權重標籤或前綴匹配標籤
- 使用
'simple'
文本搜尋配置生成,tsquery
因為您顯然希望按原樣*使用“可用”*一詞而不應用詞幹提取。- 追加**
:*
**使其成為前綴搜尋,即查找所有以’avail’ 開頭的詞位。重要提示:這是對文件中詞位(詞幹)的前綴搜尋。沒有萬用字元 ( ) 的正則表達式匹配
content ~* 'avail'
並不完全相同!後者不是左錨定的(在詞位的開頭),並且還會找到“FOOavail”等。目前尚不清楚您是想要查詢中概述的行為還是添加的正則表達式的等價物。
pg_trgm
像@Evan 已經建議的三元組索引( )是正確的工具。dba.SE上有很多相關的問題,試試搜尋一下。概述:
展示
SELECT * FROM ( VALUES ('Zend has no framework') , ('Zend Framework') ) sub(t), to_tsvector(t) AS tsv WHERE tsv @@ to_tsquery('zend <-> fram:*');
id | t | tsv ----+----------------+------------------------ 2 | Zend Framework | 'framework':2 'zend':1
相關答案(參見“優化搜尋的不同方法”一章):
電子郵件?
由於您提到了電子郵件,請注意文本搜尋解析器會辨識電子郵件並且不會將它們拆分為單獨的單詞/詞位。考慮:
SELECT ts_debug('english', 'xangr@some.domain.com')
(email,"Email address",xangr@some.domain.com,{simple},simple,{xangr@some.domain.com})
我會將分隔符
@
和.
電子郵件中的分隔符替換為空格 (' '
) 以索引包含的單詞。此外,由於您處理的是電子郵件中的姓名,而不是英語(或其他語言)單詞,我將使用
'simple'
文本搜尋配置來禁用詞幹提取和其他語言功能:使用以下命令建構
ts_vector
列:SELECT to_tsvector('simple', translate('joe.xangr@some.domain.com', '@.', ' ')) AS tsv;