PostgreSQL多结果全文搜索疑问:为何未返回全部匹配行?
为什么我的PostgreSQL全文搜索只返回部分匹配结果?
问题出在哪?
兄弟,你这个问题的核心就是拼接字符串的时候没加空格!
你看,当你直接用name || alternative_name把两个字段拼在一起时,它们是硬凑到一块的,没有分隔符:
- Johnny B的
name是Johnny B,alternative_name是The second John,拼完就变成了Johnny BThe second John——注意B和The连在一起成了BThe,这就把原本的字符串结构搞乱了,PostgreSQL的全文分词器没法正确识别后面的John。 - 而Johnny A那边运气好,拼完的字符串刚好让分词器还能抓到
John的词素,所以能返回结果,但这纯属巧合。
怎么搞定多列全文搜索?
给你几个靠谱的解决办法:
1. 手动加空格拼接
最简单的就是在两个字段之间加个空格,保证分词器能正确识别每个词:
select name from persons where to_tsvector(name || ' ' || alternative_name) @@ to_tsquery('John');
2. 用concat_ws更省心
PostgreSQL有个专门的函数concat_ws(带分隔符的拼接),不仅能自动加空格,还能处理字段为NULL的情况,比手动拼靠谱多了:
select name from persons where to_tsvector(concat_ws(' ', name, alternative_name)) @@ to_tsquery('John');
3. 数据量大的话加个索引
如果你的表数据不少,建议建个全文索引,不然每次查询都要实时分词,速度会很慢:
-- 创建基于两个字段的GIN索引,指定用english词典 create index idx_persons_fulltext on persons using gin(to_tsvector('english', concat_ws(' ', name, alternative_name)));
查询的时候记得和索引用一样的配置,这样才能用上索引:
select name from persons where to_tsvector('english', concat_ws(' ', name, alternative_name)) @@ to_tsquery('english', 'John');
这样改完,Johnny B的行肯定能被查出来啦!
内容的提问来源于stack exchange,提问作者Arnab Datta
相关产品推荐
相关产品推荐

