首页 > 解决方案 > Postgresql tsvector不搜索几个字符串

问题描述

我正在使用 PostgreSQL 11,在 search_fields 列上创建了带有 gin 索引的 tsvector。

表格测试中的数据

id   |           name           |         search_fields          
-------+--------------------------+--------------------------------

19973 | Ongoing 10x consultation | '10x' 'Ongoing' 'consultation'

19974 |  5x marketing | '5x' 'marketing'

19975 | Ongoing 15x consultation | '15x' 'Ongoing' 'consultation'

默认文本搜索配置设置为“pg_catalog.english”。

在两个查询下方输出 0 行。

select id, name, search_fields from test where search_fields @@ to_tsquery('ongoing');

id | name | search_fields 
----+------+---------------
(0 rows)


select id, name, search_fields from test where search_fields @@ to_tsquery('simple','ongoing');

id | name | search_fields 
----+------+---------------
(0 rows)

但是当我将字符串作为“10x”或“咨询”传递时,它会返回正确的输出。

任何想法,为什么它不搜索“正在进行的”单词?

之后,我使用函数 tsvector_update_trigger() 创建了触发器并更新了 search_fields 并在 postgresql.conf 文件中将 default_text_search_config 设置为 'pg_catalog.simple',然后我用 search_fields 更新了 search_fields 并输出为

select id, name, search_fields from test where search_fields @@ to_tsquery('ongoing');
 id |              name               |              search_fields              
----+---------------------------------+-----------------------------------------
  19973  | Ongoing 10x consultation | '10x':2 'consultation':3 'ongoing':1

这一次,当我运行传递“正在进行的”字符串的查询时,它会按照预期的结果输出。

select id, name, search_fields from test where search_fields @@ to_tsquery('ongoing');

id   |           name           |         search_fields          
-------+--------------------------+--------------------------------

19973 | Ongoing 10x consultation | '10x':2 'consultation':3 'ongoing':1

19975 | Ongoing 15x consultation | '15x':2 'consultation':3 'ongoing':1

根据上述实验,将 trigger 和 default_text_search_config 设置为 'pg_catalog.simple' 有助于实现结果。

现在,我不知道它不能使用 default_text_search_config 到 'pg_catalog.english' 的原因是什么。

使用tsvector时是否总是需要触发?

任何有助于理解两者之间差异的帮助将不胜感激。

谢谢,尼西特

标签: postgresqlfull-text-searchtsvector

解决方案


您没有描述最初是如何创建 search_fields 的。它构造不正确。因为我们不知道你做了什么,所以我们不知道你做错了什么。如果您正确重建它,那么它将开始工作。当您将 default_text_search_config 更改为“简单”时,您似乎已经正确地重新填充了 search_fields,这就是它起作用的原因。如果您改回“英语”并正确重新填充 search_fields,那么它也可以工作。

您并不总是需要触发器。触发器是一种方式。另一种方法是每次更新文本列时手动更新 tsvector 列。我通常最喜欢的方法是根本不存储 tsvector,而只是动态导出它:

select id, name, search_fields from test where 
    to_tsvector('english',name) @@ to_tsquery('english','ongoing');

如果要这样的话,需要指定配置,不能依赖default_text_search_config,否则表达式gin index就用不上了。此外,如果您想使用短语搜索,这种方式也不是一个好主意,因为重新检查会很慢。


推荐阅读