PostgreSQL 中文全文搜索搭建:Docker 部署 + 中文分词配置完整教程

概述

PostgreSQL 内置了全文搜索引擎,用 tsvector 和 tsquery 就能做关键词搜索、相关度排序。但默认配置只支持英文分词,中文文本直接搜基本没用。

要支持中文,需要装 zhparser 或 pg_jieba 这类中文分词插件。zhparser 基于 HDWK 分词算法,性能不错,是社区最常用的选择。

本文用 Docker 跑 PG 容器,顺手把 zhparser 编译安装好,配置完就能搜中文了。

准备工作

  • 一台 VPS(1 核 CPU、1 GB 内存起步,中文分词不算吃资源)
  • 已安装 Docker 和 Docker Compose
  • 有 sudo 权限
  • 磁盘 5 GB 以上

步骤

第一步:创建项目目录

mkdir -p ~/pg-fts && cd ~/pg-fts

第二步:写 docker-compose.yml

version: '3.8'

services:
  postgres:
    image: postgres:16
    container_name: pg-fts
    restart: unless-stopped
    environment:
      POSTGRES_USER: ftsuser
      POSTGRES_PASSWORD: ftspass2024!
      POSTGRES_DB: ftsdb
    volumes:
      - pgfts_data:/var/lib/postgresql/data
      - ./init-db.sh:/docker-entrypoint-initdb.d/init-db.sh
    ports:
      - "5432:5432"

volumes:
  pgfts_data:

注意:把 POSTGRES_PASSWORD 改成你自己的密码。

第三步:写初始化脚本

在项目目录下新建 init-db.sh:

#!/bin/bash
set -e

# 安装 zhparser 扩展
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
  CREATE EXTENSION IF NOT EXISTS zhparser;
  DROP TEXT SEARCH CONFIGURATION zhparser;
  CREATE TEXT SEARCH CONFIGURATION zhparser ( PARSER = zhparser );
  ADD MAPPING FOR n,v,a,i,e,l WITH simple;
EOSQL

保存后给执行权限:

chmod +x init-db.sh

第四步:启动服务

docker-compose up -d

启动后检查容器状态:

docker-compose ps

应该显示 Up 状态。如果启动失败,用 docker-compose logs 查看报错。

第五步:验证 zhparser 已生效

docker-compose exec postgres psql -U ftsuser -d ftsdb -c "SELECT * FROM pg_ts_parser LIMIT 1;"

输出里应该有 zhparser 一行。再确认配置:

docker-compose exec postgres psql -U ftsuser -d ftsdb -c "SELECT cfgname FROM pg_ts_config WHERE cfgname = 'zhparser';"

应该输出 zhparser。

第六步:建表并测试搜索

docker-compose exec postgres psql -U ftsuser -d ftsdb <<'SQL'
CREATE TABLE articles (
  id SERIAL PRIMARY KEY,
  title TEXT,
  content TEXT,
  search_vector TSVECTOR
);

-- 创建触发器,自动维护 tsvector
CREATE OR REPLACE FUNCTION update_search_vector() RETURNS TRIGGER AS \$\$
BEGIN
  NEW.search_vector :=
    to_tsvector('zhparser', COALESCE(NEW.title, '') || ' ' || COALESCE(NEW.content, ''));
  RETURN NEW;
END;
\$\$ LANGUAGE plpgsql;

CREATE TRIGGER tsvector_update BEFORE INSERT OR UPDATE ON articles
  FOR EACH ROW EXECUTE FUNCTION update_search_vector();

-- 插入测试数据
INSERT INTO articles (title, content) VALUES
  ('Docker 容器入门教程', 'Docker 是一个开源的应用容器引擎,开发者可以打包应用到容器里'),
  ('PostgreSQL 全文搜索指南', 'PostgreSQL 提供了强大的全文搜索功能,支持中文分词'),
  ('Kubernetes 部署实践', 'Kubernetes 是容器编排平台,可以帮助管理大规模 Docker 容器集群'),
  ('Python 数据处理技巧', 'Python 是数据科学主流语言,pandas 和 numpy 是常用工具包');

-- 建索引加速搜索
CREATE INDEX idx_articles_vector ON articles USING GIN(search_vector);

-- 测试搜索
SELECT id, title, ts_rank(search_vector, query) AS rank
FROM articles, to_tsquery('zhparser', 'Docker OR PostgreSQL') AS query
ORDER BY rank DESC;
SQL

输出应该显示标题和搜索相关度排名,“Docker” 和 “PostgreSQL” 两篇排在最前面。

验证

确认搜索功能正常

docker-compose exec postgres psql -U ftsuser -d ftsdb <<'SQL'
-- 搜"容器",应该看到 Docker 和 Kubernetes 两篇
SELECT id, title, to_tsvector('zhparser', title) AS parsed
FROM articles
WHERE search_vector @@ to_tsquery('zhparser', '容器');
SQL

确认索引生效

docker-compose exec postgres psql -U ftsuser -d ftsdb -c "SELECT indexname, indexdef FROM pg_indexes WHERE tablename = 'articles';"

应该看到 idx_articles_vector 使用 GIN 索引。

常见问题

Q: zhparser 编译时报"Makefile: no such file"

PostgreSQL 官方镜像不内置 zhparser,需要通过 init-db.sh 自动从源码编译。如果容器里网络不通,先确保 Docker 能访问外网:

docker-compose exec postgres apt-get update && apt-get install -y make gcc libpq-dev

Q: 搜中文返回空结果?

先检查分词结果:

docker-compose exec postgres psql -U ftsuser -d ftsdb -c "SELECT to_tsvector('zhparser', 'Docker 容器入门教程');"

如果输出是空 {},说明分词器没装好,检查 init-db.sh 是否正确执行。

Q: 中文分词效果不理想,想换 jieba?

把 init-db.sh 里的 zhparser 换成 pg_jieba:

# 安装 jieba
docker-compose exec postgres apt-get install -y python3-pip
pip3 install jieba

# 创建扩展
psql -c "CREATE EXTENSION pg_jieba;"
psql -c "SELECT * FROM pg_ts_parser LIMIT 1;"

Q: 如何远程连接?

PostgreSQL 默认只监听 localhost。容器内修改配置:

docker-compose exec postgres sh -c "echo \"listen_addresses = '*'\" >> /var/lib/postgresql/data/postgresql.conf"
docker-compose restart postgres

同时在 pg_hba.conf 里加允许远程的规则:

docker-compose exec postgres sh -c "echo \"host all all 0.0.0.0/0 md5\" >> /var/lib/postgresql/data/pg_hba.conf"
docker-compose restart postgres

下一步

搜到数据只是第一步。生产环境建议加上备份、监控和 SSL 加密。

数据量大了之后,GIN 索引维护成本会上升,可以考虑用 pg_trgm 做模糊匹配补充。

装好了,下一篇可以聊聊如何用 Elasticsearch 做更复杂的搜索场景。

这篇文章对你有帮助吗?