为什么这个postgresql全文搜索查询返回ts_rank为0?

时间:2016-02-04 17:24:32

标签: postgresql full-text-search fuzzy-search tsvector

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

我想在一个表格中找到一份全国性的商家列表。我创建了一个结合了商业名称和城市的ts矢量,这样我就可以进行类似"内陆亚特兰大"的搜索。

我还通过附加":"使用搜索的通配符功能来实现自动完成功能。搜索模式并插入" &安培; "在关键字之间,所以搜索模式"内陆atl"变成了"内陆& ATL:"在使用to_tsquery()转换为查询之前。

这是我目前遇到的问题。 如果搜索模式输入为" 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',$1) 
ORDER BY ts_rank(textsearchable_index_col, to_tsquery('simple',$1)) DESC

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

感谢

1 个答案:

答案 0 :(得分:1)

这里的问题是您正在搜索商家名称,正如@Daniel正确指出的那样 - 'english'字典无法帮助您找到非字典字词的“模糊”匹配喜欢“Outback Steakhouse”等;

'simple'字典

'simple'字典本身也无法帮助您,在您的情况下,商家名称仅适用于完全匹配,因为所有字词都是不受限制的。< / p>

'simple'字典+ pg_trgm

但是,如果您将<{1}}词典与 pg_trgm模块一起使用,那么它将正是您所需要的,尤其是:

  • 对于'simple'你不需要担心停止词语“黑客”,你将得到所有未被扼杀的词汇;
  • 使用to_tsvector('simple','<business name>')中的similarity(),您将获得最高“等级” 为了最好的比赛,

看看这个:

pg_trgm

结果:

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订购,您将能够获得所需。

更新

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

选项#1。

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

view_business_favorite_count

查询看起来像这样:

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

选项#2。

使用全文搜索,您需要:

  • 创建一个单独的表格,例如SELECT id, name, address, city, state, likes, similarity(name,$1) AS trgm_rank -- similarity score FROM view_business_favorite_count WHERE name % $1 -- trgm search ORDER BY trgm_rank DESC; ,您将在其中存储2列:第一列将保留所有词汇来自unnested_business_names函数,第二列将具有{{ 1}}(to_tsvector('simple',name) vbfc_id表格的FK;
  • 为列添加id索引,其中包含lexemes;
  • from view_business_favorite_count添加触发器,该触发器将更新或插入或删除trgm中的新值以使所有字词保持最新