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

时间:2019-02-07 14:28:09

标签: postgresql full-text-search

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

为此,“ *”通配符必须附加到最后一个tsquery lexeme。例如。如果用户键入"The fat ra",则tsquery应该为'fat' & 'ra':*

如果我将whildcart附加到输入字符串中,并使用plainto_tsquery函数进行解析,则会删除plainto_tsquery("The fat ra" || ":*") => 'fat' & 'ra'的whildcard。

使用to_tsquery函数手动构造tsquery要求对字符串进行大量修改(例如修剪空格和其他特殊字符,用&字符替换空格)以使该函数接受它。

有更简单的方法吗?

1 个答案:

答案 0 :(得分:1)

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

=> SELECT ((to_tsquery('foo <-> bar')::text || ':*')::tsquery);
      tsquery      
-------------------
 'foo' <-> 'bar':*

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

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

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

phraseto_tsquery使指定许多必须彼此相邻的单词变得容易:

=> SELECT phraseto_tsquery('foo baz');
 phraseto_tsquery 
------------------
 'foo' <-> 'baz'

将它们放在一起:

=> SELECT (phraseto_tsquery('The fat ra')::text || ':*')::tsquery;
     tsquery      
------------------
 'fat' <-> 'ra':*

根据您的需求,一种更简单的方法可能是直接使用字符串而不是类型转换来构建tsquery:

=> SELECT $$'fat' <-> 'ra':*$$::tsquery;
     tsquery      
------------------
 'fat' <-> 'ra':*