用Python和Postgresql实现中文全文搜索
全文检索的基本原理就是,把文本分词,提取出结构化数据(创建索引),根据用户查询请求,使用索引查找到目标(搜索索引)。这个博客程序使用了PostgreSQL
数据库和Peewee
ORM,为了实现这个目标,我们需要使用PostgreSQL
的全文检索插件,这里使用的是zhparser。
PostgreSQL的配置
首先根据系统安装PostgreSQL
数据库,建议根据官方文档安装,这里使用 PostgreSQL 14 版本。
因为 zhparser
实际使用的是 SCWS
分词,要安装 SCWS 插件,
wget -q -O - http://www.xunsearch.com/scws/down/scws-1.2.3.tar.bz2 | tar xf -
cd scws-1.2.3 ; ./configure ; make install
然后安装zhparser
git clone --depth=1 https://github.com/amutu/zhparser.git
make && make install
创建extension 打开psql,运行以下脚本,
CREATE EXTENSION zhparser;
这里的配置适用于普遍情况,如有特殊需求,请参考对应网站进行配置, 在2021年的现在,建议一切部署都通过docker实现,这里有一个我的Docker配置,可以快速搭建起一个PostgreSQL实例,包含了全文检索需要的插件
https://github.com/lerry/postgresql-docker
数据库配置
这里假设你已经创建好了你的数据库,和对应的数据表,以本博客程序为例,
CREATE TABLE entry (
id SERIAL PRIMARY KEY,
uid integer NOT NULL,
slug character varying(50) NOT NULL,
title character varying(50) NOT NULL,
content text NOT NULL,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
status smallint NOT NULL,
password character varying(50),
allow_comment smallint NOT NULL,
view_times integer NOT NULL,
cover text
);
创建全文检索相关的配置,注意最后两行要根据你实际的数据库字段修改,
CREATE EXTENSION zhparser;
CREATE TEXT SEARCH CONFIGURATION zh (PARSER = zhparser);
ALTER TEXT SEARCH CONFIGURATION zh ADD MAPPING FOR n,v,a,i,e,l WITH simple;
CREATE INDEX fts_idx_title ON entry USING gin(to_tsvector('zh',title));
CREATE INDEX fts_idx_content ON entry USING gin(to_tsvector('zh',content));
查询
用peewee ORM查询
result = Entry.select().where(Entry.status == 1, Match(Entry.title, q, 'zh') | Match(Entry.content, q, 'zh')) \
.order_by(Entry.created_at.desc()).limit(options.PAGE_LIMIT)
这里的zh对应这里的zh CREATE TEXT SEARCH CONFIGURATION zh (PARSER = zhparser);
对应的SQL,
SELECT * FROM entry WHERE to_tsvector('zh', title) @@ to_tsquery('zh', 'python') OR to_tsvector('zh', content) @@ to_tsquery('zh', 'python')
这里有个小插曲,最早我用peewee的时候,它的Match
函数,第三个参数,语言配置并没有生效,于是我提交了一个PR,修正了这个问题,很快这个PR被合并到代码库了,这也是我第一次参与到实际的开源项目。
PR在这里,https://github.com/coleifer/peewee/pull/1379/files
作者: Lerry
发表时间:2021-01-22
版权说明:CC BY-NC-ND 4.0 DEED