必须用to_tsvector()并显式指定语言配置(如'english'或'zh_cn'),否则默认simple配置无法分词中文、归一英文词形或过滤停用词;中文需安装zhparser等插件,且to_tsvector与to_tsquery配置必须一致。

直接结论:用 to_tsvector() 是必须的,但只调用它远远不够——它不自动分词中文,也不处理停用词和词形归一化,除非你显式指定配置(config)。
为什么 to_tsvector('text') 不能直接用
很多人写 to_tsvector('hello world'),结果发现中文全被当做一个长串、英文复数没归一、停用词(如“the”“a”)还在里面。这是因为 PostgreSQL 默认使用 simple 配置,仅做小写+空格切分,不走任何语言规则。
常见错误现象:
- 查
'数据库'返回不了含“数据库系统”或“数据库设计”的记录(未分词) - 查
'running'匹配不到'runs'或'ran'(没词干提取) - 查
'the cat'实际生成'the':1 'cat':2,导致@@ to_tsquery('cat')失败('the'是停用词,但simple不删)
正确做法是:始终带语言配置参数,例如 to_tsvector('english', col) 或 to_tsvector('zh_cn', col)(后者需先装 zhparser)。
中文分词必须配 zhparser 或类似插件
PostgreSQL 原生不支持中文分词。to_tsvector('chinese', ...) 是无效的——没有叫 chinese 的内置配置。
可行路径只有两个:
- 用
zhparser(推荐):安装后创建配置zh_cn,再调用to_tsvector('zh_cn', '江淮杜伏威')→ 得到'杜伏威':3 '江淮':1 - 用
pg_jieba或pg_scws:类似流程,但词典策略和性能表现不同,比如pg_jieba对社交媒体短文本更敏感
注意:zhparser 的配置名(如 zh_cn)必须和 to_tsquery() 中用的一致,否则匹配失败——这是最常被忽略的兼容性坑。
to_tsvector() 的三个关键参数影响结果
函数签名是 to_tsvector([config regconfig,] document text),其中 config 可选但强烈建议显式传入:
- 省略 config → 默认用
get_current_ts_config()返回值(通常是pg_catalog.simple),结果不可控 - 传错 config 名(如写成
'chinese'而非'zh_cn')→ 报错ERROR: text search configuration "chinese" does not exist - 对多语言混合字段(如中英混排产品描述),不能靠一个 config 覆盖全部;得拆字段或用条件表达式,例如:
COALESCE(to_tsvector('zh_cn', zh_part), to_tsvector('english', en_part))
性能提示:在 WHERE 条件里直接写 to_tsvector('zh_cn', content) 会每次查询都重算,务必配合 GIN 索引,例如:CREATE INDEX idx_gin_zh ON articles USING GIN (to_tsvector('zh_cn', content))。
容易被忽略的细节:标点、空格与位置信息
to_tsvector() 输出的 tsvector 值里,每个词位(lexeme)自带位置编号,比如 '速度':2 '激情':5。这个位置信息是后续做短语搜索()、邻近搜索()的基础。
但要注意:
- 原始文本里的标点(如顿号、破折号)在分词时可能被吞掉或转成空格,导致位置偏移;测试时用
SELECT to_tsvector('zh_cn', '速度、激情')看实际输出,别凭感觉假设 - 连续空格、换行符会被压缩,但某些插件(如
pg_jieba)对 HTML 标签不敏感,若字段含,得先用速度
strip_tags()类函数清洗 - 位置编号从 1 开始,且只计“有效词位”,停用词和标点不占位——所以
'a fat cat'在english下变成'fat':2 'cat':3,不是'fat':3 'cat':4
真正难的不是调用函数,而是让 to_tsvector() 的输出和 to_tsquery() 的解析逻辑严丝合缝对齐;配置不一致、插件未启用、索引未建——三者错一个,全文检索就退化成 LIKE。










