use*_*231 12 postgresql full-text-search pattern-matching
我必须搜索带连字符的单词,例如“早安”、“晚安”等。
我的查询是:
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');
Run Code Online (Sandbox Code Playgroud)
执行此查询时,我还会分别获得“good”和“morning”的结果。但我想要完全匹配的单词和片段。
(因为ts_content
我使用相同的默认配置english
来创建tsvector
.)
如何在 PostgreSQL 全文搜索中搜索此类带连字符的单词?
Erw*_*ter 10
这里的关键词是短语搜索,它是在Postgres 9.6 中引入的。
使用tsquery
FOLLOWED 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');
Run Code Online (Sandbox Code Playgroud)
phraseto_tsquery('english', 'good-morning')
生成这个tsquery
:
'good-morn' <-> 'good' <-> 'morn'
Run Code Online (Sandbox Code Playgroud)
由于“早上好”被标识为asciihword
(带连字符的 ASCII 字),因此在成分之前添加了词干完整的字。手册:
解析器可能会从同一段文本中产生重叠的标记。例如,带连字符的单词将作为整个单词和每个组件报告:(后跟示例)
to_tsvector()
基本上在另一端做同样的事情,所以一切都匹配。这允许带有连字符的细粒度选项。上面只找到带有连字符的“早上好”(或衍生出相同的变体)。要查找所有带有“good”后跟“morn”的字符串(或衍生为相同的变体),请使用phraseto_tsquery('english','good morning')
生成此 tsquery:'good' <-> 'morn'
OTOH,您可以通过添加另一个过滤器来强制精确匹配,例如:
...
AND content ~* 'good-morning' -- case insensitive regexp match
Run Code Online (Sandbox Code Playgroud)
或者:
...
AND content ILIKE '%good-morning%'
Run Code Online (Sandbox Code Playgroud)
对人眼来说似乎有点多余,但通过这种方式,您可以获得快速的全文索引支持和 精确匹配。
后者大部分是等价的,但不同(较少)的字符在LIKE
模式中具有特殊含义,可能需要转义。有关的:
演示运算符的示例<N>
:
phraseto_tsquery('english', 'Juliet and the Licks')
生成这个tsquery
:
'juliet' <3> 'lick'
Run Code Online (Sandbox Code Playgroud)
<3>
这意味着lick
必须是juliet
.之后的第三个词素。
归档时间: |
|
查看次数: |
4639 次 |
最近记录: |