PostgreSQL中全文检索与模糊检索的结合

iqih9akk  于 2023-03-17  发布在  PostgreSQL
关注(0)|答案(1)|浏览(145)

我想在postgresql中实现一个结合了模糊搜索的全文搜索。对于我的测试区域,我跟踪了这篇文章:https://blog.lateral.io/2015/05/full-text-search-in-milliseconds-with-postgresql/,一切都很好。但有时我会遇到searach字符串中有空格和没有空格的情况,如下所示:
在我的“标题”列中有一个类似“test123”的条目。我的搜索字符串看起来像“test 123”*,其中有一个空格 *。我如何在此测试用例中获得匹配?
我的search-sql-query看起来像:

SELECT * 
FROM test, plainto_tsquery('test:*&123:*') as q 
WHERE (tsv @@ q)

result: 0 rows

所以我试着去弄清楚我是否可以结合使用pg_trgm和ts_vector,但是我找不到一个解决方案,你有什么想法吗?

avwztpqn

avwztpqn1#

正如解析文档所述:
...plainto_tsquery将无法识别其输入中的tsquery运算符、权重标签或前缀匹配标签...
plainto_tsqueryphraseto_tsquery是方便的函数,它们使按完整字符串搜索变得更容易,但它们不支持所有功能。请改用to_tsquery,它接受完整的搜索语法:

SELECT * 
FROM test, to_tsquery('testing:* & 123:*') as q 
WHERE (tsv @@ q)

这个函数还要求你规范化搜索查询,就像规范化to_tsvector搜索的文本一样,但是对于一些字符串函数来说,这很容易做到:

SELECT string_agg(lexeme || ':*', ' & ' order by positions) 
FROM unnest(to_tsvector('testing 123'))

这基本上是从to_tsvector获取单个标记,将:*附加到每个标记,然后将它们与&连接以创建单个字符串。上面的示例获取testing 123并生成testing:* & 123:*,然后可以直接与to_tsquery一起使用以获得不受规范化影响的模糊匹配。
您可以将其全部合并到CTE中,使其变得简单:

WITH search AS (
    SELECT to_tsquery(string_agg(lexeme || ':*', ' & ' order by positions)) AS query
    FROM unnest(to_tsvector('enter your search query here'))
)
SELECT test.*
FROM test, search
WHERE (test.tsv @@ search.query)

这里假设表中有一个数据类型为tsquerytsv列,该列是预先生成的,而不是在每次查询时创建(这样会慢很多)。PG12+支持generated columns,它可以自动更新该列。
更深入的答案在我的博客:https://manigandham.com/post/fuzzy-fulltext-search-postgresql

相关问题