为什么此 postgresql 全文搜索查询返回 ts_rank of 0?

why is this postgresql full text search query returning ts_rank of 0?

在我投资使用 solr 或 lucene 或 sphinx 之前,我想尝试使用 postgresql 全文搜索在我的系统上实现搜索功能。

我在 table 中有一份全国企业列表,我想搜索。我创建了一个结合了公司名称和城市的 ts 向量,这样我就可以像 "outback atlanta" 这样进行搜索。

我还通过在搜索模式中附加“:”并在关键字之间插入“&”来使用搜索的通配符功能实现自动完成功能,因此搜索模式"outback atl" 在使用 to_tsquery().

转换为查询之前变成 "outback & atl:"

这是我目前运行正在解决的问题。 如果搜索模式输入为 "ou",则会返回许多 "Outback Steakhouse" 条记录。 如果搜索模式输入为 "out",则不会返回任何结果。 如果搜索模式输入为 "outb",则会返回许多 "Outback Steakhouse" 条记录。

做了一点调试,我想到了这个:

select ts_rank(to_tsvector('Outback Steakhouse'),to_tsquery('ou:*')) as "ou",
ts_rank(to_tsvector('Outback Steakhouse'),to_tsquery('out:*')) as "out",
ts_rank(to_tsvector('Outback Steakhouse'),to_tsquery('outb:*')) as "outb"

结果如下:

ou          out   outb
0.0607927   0     0.0607927

我做错了什么?

这是pg全文搜索的限制吗?

我可以用我的字典或配置来解决这个异常吗?

更新: 我认为 "out" 可能是停用词。

当我 运行 这个调试查询时,我没有得到 "out"

的任何词位
SELECT * FROM ts_debug('english','out back outback');

alias         description       token     dictionaries      dictionary      lexemes 
asciiword     Word all ASCII    out       {english_stem}    english_stem    {}
blank         Space symbols               {}            
asciiword     Word all ASCII    back      {english_stem}    english_stem    {back}
blank         Space symbols               {}            
asciiword     Word all ASCII    outback   {english_stem}    english_stem    {outback}

所以现在请问如何修改停用词列表来删除一个词?

更新: 这是我目前使用的查询:

select id,name,address,city,state,likes 
from view_business_favorite_count 
where textsearchable_index_col @@ to_tsquery('simple',) 
ORDER BY ts_rank(textsearchable_index_col, to_tsquery('simple',)) DESC

当我执行查询时(我使用的是 Strongloop Loopback + Express + Node),我将模式传入以替换 $1 参数。模式(如上所述)看起来像 "keyword:" 或 "keyword1 & keyword2 & ... & keywordN:"

谢谢

这里的问题是您正在搜索 企业名称 并且正如@Daniel 正确指出的那样 - 'english' 字典不会帮助您找到 "fuzzy" 匹配非字典词,如 "Outback Steakhouse" 等;

'simple'字典

'simple' 字典本身对您也没有帮助,在您的情况下 企业名称 仅适用于 完全匹配 因为所有的词都是无词干的。

'simple'字典+pg_trgm

但是,如果您将 'simple' 字典与 pg_trgm 模块一起使用 - 它正是您所需要的,特别是:

  • 对于to_tsvector('simple','<business name>')你不需要担心停用词"hack",你会得到所有的词素;
  • 使用 pg_trgm 中的 similarity() 你会得到最高的 "rank" 为了获得最佳匹配,

看看这个:

WITH pg_trgm_test(business_name,search_pattern) AS ( VALUES
  ('Outback Steakhouse','ou'),
  ('Outback Steakhouse','out'),
  ('Outback Steakhouse','outb')
)
SELECT business_name,search_pattern,similarity(business_name,search_pattern)
FROM pg_trgm_test;

结果:

   business_name    | search_pattern | similarity 
--------------------+----------------+------------
 Outback Steakhouse | ou             |        0.1
 Outback Steakhouse | out            |       0.15
 Outback Steakhouse | outb           |        0.2
(3 rows)

通过 similarity 订购 DESC 您将能够得到您所需要的。

更新

对于您的情况,有 2 种可能的选择。

选项#1。

只需为 view_business_favorite_count table 中的 name 列创建 trgm 索引;索引定义可能如下:

CREATE INDEX name_trgm_idx ON view_business_favorite_count USING gin (name gin_trgm_ops);

查询看起来像这样:

SELECT 
  id,
  name,
  address,
  city,
  state,
  likes,
  similarity(name,) AS trgm_rank -- similarity score
FROM 
  view_business_favorite_count
WHERE 
  name %  -- trgm search
ORDER BY trgm_rank DESC;

选项#2。

使用全文搜索,您需要:

  • 创建一个单独的 table,例如 unnested_business_names,您将在其中存储 2 列:第 1 列将保留 all 来自 [=29= 的词素] 函数,第二列将有 vbfc_id(FK for id from view_business_favorite_count table);
  • 为包含词位的列添加 trgm 索引;
  • unnested_business_names 添加触发器,它将更新或插入或删除 view_business_favorite_count 中的新值以使所有单词保持最新