在我投资使用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:"
感谢
答案 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
订购,您将能够获得所需。
对于您的情况,有两种可能的选择。
只需为DESC
表中的name
列创建trgm索引;索引定义可能如下:
view_business_favorite_count
查询看起来像这样:
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
函数,第二列将具有{{ 1}}(to_tsvector('simple',name)
vbfc_id
表格的FK; id
索引,其中包含lexemes; from view_business_favorite_count
添加触发器,该触发器将更新或插入或删除trgm
中的新值以使所有字词保持最新