Postgresql

如何在 PostgreSQL 全文搜尋中搜尋連字元?

  • April 12, 2021

我必須搜尋諸如“早安”、“晚安”等連字元的單詞。

我的查詢是:

select id, ts_headline(content,
                      to_tsquery('english','good-morning'),
                      'HighlightAll=true MaxFragments=100 FragmentDelimiter=$') 
from table 
where ts_content @@ to_tsquery('english','good-morning');

執行此查詢時,我還分別得到*“好”“早上”的*結果。但我想要完全匹配的單詞和片段。

(因為ts_content我使用相同的預設配置english來創建tsvector。)

如何在 PostgreSQL 全文搜尋中搜尋此類連字元?

這裡的關鍵詞是片語搜尋**,它是在Postgres 9.6**中引入的。

使用tsqueryFOLLOWED BY 運算符**<->**相關<N>運算符之一。或者更好的是,使用該函式phraseto_tsquery()生成您的tsquery.

引用手冊,它…

生成tsquery搜尋片語,忽略標點符號

和:

phraseto_tsquery行為很像plainto_tsquery,除了它<->在倖存的單詞之間插入 (FOLLOWED BY) 運算符而不是&(AND) 運算符。此外,停用詞不是簡單地丟棄,而是通過插入<N>運算符而不是<-> 運算符來解釋。此函式在搜尋精確的詞位序列時很有用,因為 FOLLOWED BY 運算符檢查詞位順序而不僅僅是所有詞位的存在。

您的查詢將像這樣工作:

select id
    , ts_headline(content, phraseto_tsquery('english', 'good-morning')
                         , 'HighlightAll=true MaxFragments=100 FragmentDelimiter=$') 
from   tbl 
where  ts_content @@ phraseto_tsquery('english','good-morning');

phraseto_tsquery('english', 'good-morning')生成這個tsquery

'good-morn' <-> 'good' <-> 'morn'

由於“早安”被標識為asciihword(帶連字元的 ASCII 詞),因此在組件之前添加了詞幹完整的詞。手冊:

解析器可以從同一段文本生成重疊標記。例如,一個連字元的單詞將被報告為整個單詞和每個組件:(後面是一個範例)

to_tsvector()基本上在另一端做同樣的事情,所以一切都匹配。這允許帶有連字元的細粒度選項。以上僅找到帶有連字元(或相同的變體)的“早安”。要查找所有帶有“good”後跟“morn”的字元串(或衍生相同的變體),請使用phraseto_tsquery('english','good morning')生成此 tsquery:'good' <-> 'morn'

OTOH,您可以通過添加另一個過濾器來強制執行完全匹配,例如:

...
AND content ~* 'good-morning'  -- case insensitive regexp match

或者:

...
AND content ILIKE '%good-morning%'

對人眼來說似乎有點多餘,但通過這種方式,您可以獲得快速的全文索引支持 完全匹配。

後者大部分是等價的,但不同(更少)字元在LIKE模式中具有特殊含義,可能需要轉義。有關的:

展示運算符的範例<N>

phraseto_tsquery('english', 'Juliet and the Licks')生成這個tsquery

'juliet' <3> 'lick'

<3>這意味著lick必須是 . 之後的第三個詞位juliet

引用自:https://dba.stackexchange.com/questions/204588