如何在 PostgreSQL 中将前缀匹配附加到 tsquery

yau*_*nka 6 postgresql full-text-search

我正在尝试利用 PostgreSQL 的全文搜索功能,特别是当用户键入某些搜索文本时,我想向他显示结果,并假设最后一个单词不完整。

为此,需要将“*”通配符附加到最后一个 tsquery 词素。例如,如果用户在"The fat ra"tsquery 中键入应该是'fat' & 'ra':*.

如果我将通配符附加到输入字符串并使用plainto_tsquery函数解析它,那么通配符将被删除plainto_tsquery("The fat ra" || ":*") => 'fat' & 'ra'

to_tsquery函数手动构造一个tsquery,需要对字符串进行大量修改(比如修剪空格等特殊字符,用&符号替换空格),让函数接受。

有没有更简单的方法来做到这一点?

小智 9

您可以通过将 tsquery 中的最后一个词素转换为字符串,附加 ':*',然后将其转换回 tsquery 来使 tsquery 中的最后一个词素成为前缀匹配:

=> SELECT ((to_tsquery('foo <-> bar')::text || ':*')::tsquery);
      tsquery      
-------------------
 'foo' <-> 'bar':*
Run Code Online (Sandbox Code Playgroud)

对于您的用例,您需要使用<->而不是&要求单词彼此相邻。以下是它们的不同之处的演示:

=> SELECT 'foo bar baz' @@ tsquery('foo & baz');
 ?column? 
----------
 t
(1 row)

=> SELECT 'foo bar baz' @@ tsquery('foo <-> baz');
 ?column? 
----------
 f
(1 row)
Run Code Online (Sandbox Code Playgroud)

phraseto_tsquery 可以很容易地指定许多必须彼此相邻的单词:

=> SELECT phraseto_tsquery('foo baz');
 phraseto_tsquery 
------------------
 'foo' <-> 'baz'
Run Code Online (Sandbox Code Playgroud)

把它们放在一起:

=> SELECT (phraseto_tsquery('The fat ra')::text || ':*')::tsquery;
     tsquery      
------------------
 'fat' <-> 'ra':*
Run Code Online (Sandbox Code Playgroud)

根据您的需要,一种更简单的方法可能是直接使用字符串构建 tsquery,然后进行强制转换:

=> SELECT $$'fat' <-> 'ra':*$$::tsquery;
     tsquery      
------------------
 'fat' <-> 'ra':*
Run Code Online (Sandbox Code Playgroud)