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

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

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

我想在表格中搜索全国范围内的企业列表。我创建了一个结合了企业名称和城市的 ts 矢量,以便我可以进行“亚特兰大内陆”等搜索。

我还通过使用搜索的通配符功能来实现自动完成功能,方法是将“:”附加到搜索模式并在关键字之间插入“&”,因此搜索模式“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',$1) 
ORDER BY ts_rank(textsearchable_index_col, to_tsquery('simple',$1)) DESC

当我执行查询时(我使用 Strongloop Loopback + Express + Node),我传递模式来替换 $1 参数。该模式(如上所述)将类似于“keyword:”或“keyword1 & keywords2 & ... & keywordsN:

谢谢

最佳答案

这里的问题是您正在搜索公司名称,正如@Daniel正确指出的那样 - 'english'字典不会帮助您找到非字典单词的“模糊”匹配,例如“Outback Steakhouse”等;

'simple'字典

'simple'字典本身对您也没有帮助,在您的情况下,公司名称仅适用于完全匹配,因为所有单词均未词干。

'simple'字典+ pg_trgm

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

  • 对于 to_tsvector('simple','<business name>')您无需担心停用词“hack”,您将得到所有词素的词干;
  • 使用 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 DESC你将能够得到你需要的东西。

更新

根据您的情况,有 2 种可能的选择。

选项#1。

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

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,$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 ,您将在其中存储 2 列:第一列将保留 to_tsvector('simple',name) 中的所有 词位。函数,第二列将有 vbfc_id (FK 为 id from view_business_favorite_count 表);
  • 添加trgm包含词位的列的索引;
  • unnested_business_names 添加触发器,这将更新或插入或删除 view_business_favorite_count 中的新值使所有单词保持最新

关于postgresql - 为什么这个 postgresql 全文搜索查询返回 ts_rank 为 0?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35207579/

相关文章:

sql - Hypertable 与 HBase 以及 BigTable 与 SQL

Java ResultSet.getTimestamp() 将毫秒附加到输出

sql-server - 为什么我的查询这么慢? (SQL Server 2008 全文搜索怪异)

elasticsearch - 可以在elasticsearch的 “fuzzy_transpositions”查询中将 “false”设置为 “multi_match”吗?

Python 模糊匹配(FuzzyWuzzy)——只保留最佳匹配

postgresql - 将 Postgis SRID 与 Redis 的球形模型相匹配?

sql - 对 JSONB 数组字段中的所有项目求和

Azure认知搜索如何使用AND运算符精确匹配字段

search - 关于多方面搜索软件堆栈的建议

python - 如何使用 difflib 和 pandas 模糊匹配电影片名?