世界上最伟大的投资就是投资自己的教育

首页PostgreSQL
随风 · 练气

PostgreSQL 的全文检索系统之基本介绍 (一)

随风发布于3842 次阅读

1. Full Text Search 介绍

如果要实现一个站内搜索的功能,可能可以这么办,假如你的网站是个放博客的,那么可能有博客这张表,要搜索的时候,用 SQL 语句就好了,用 where like,但是这样不够好,因为你只能搜索包含或未包含的,不能像百度那样,根据关键词来搜索,也就是分词系统。我们来介绍一下,全文检索是搜索引擎的一部分,它首先得有数据,有了数据,要根据数据来分词,例如"this is a cat"就可以分成四个词,分别是"this","is", "a", "cat",或许像这些不太重要的"is","a", "this"的停止词 (stop word) 可能会被去掉,那就剩下一个词,这只是规则而已,不管怎样,不管是中文,英文,都是会切成一个个词。根据词来建立索引。索引就先理解为书中的目录,建立索引是要消耗磁盘空间的,想下就清楚了,不然索引存哪啊。索引建立好了,用户一搜索关键词,假如用户搜索了"cat",刚好命中了那个建立过的关键词,那就会通过索引把相关的记录取出来。这就是一个全文检索系统啦。只是要实现一个较完整的全文检索系统,那是需要好多功能的,例如实时搜索,关键词提示,错误提示,还有排名等。PostgreSQL 作为一个关系型数据库系统,它本身就支持全文检索,它比其他数据库支持得更好。通过简单的扩展,还能实现中文检索。这是后话。

2. PostgreSQL 的文本匹配

接下来,我们用 PostgreSQL 的 tsvector 等命令处理器来测试分词和文本匹配。先来看一个例子

postgres=# SELECT 'hello world hfpp2012'::tsvector @@ 'hello'::tsquery;

输出的结果是这样的。

 ?column? 
----------
 t
(1 row)

t 就是 true,说明是匹配成功的。如果是 f,那就是 false,表示匹配不成功。

上面语句的意思是总共有三个词,"hello world hfpp2012",然后用"hello"来匹配,相当于数据库存了三个词,在搜索引擎输入框输入了"hello",因为数据库是有"hello"这个词的,所以是能匹配到的。

再试试下面的例子。

postgres=# SELECT 'hello world hfpp2012'::tsvector @@ 'hello & world'::tsquery;
 ?column? 
----------
 t
(1 row)

"&"符号是停止符,是不被索引的,因为没有意义啊。也就不存储在数据中了。PostgreSQL 有一条规则就是

"Define stop words that should not be indexed."

还有另一种写法是这样的。

postgres=# SELECT 'hello & world'::tsquery @@ 'hello world hfpp2012'::tsvector;
 ?column? 
----------
 t
(1 row)

来搜索中文的试下

rails365_pro=# SELECT '号'::tsquery @@ '2015 - Rails365 Inc. All rights reserved. | 粤ICP备15004902号-2'::tsvector;
 ?column? 
----------
 f
(1 row)

rails365_pro=# SELECT 'Rails365'::tsquery @@ '2015 - Rails365 Inc. All rights reserved. | 粤ICP备15004902号-2'::tsvector;
 ?column? 
----------
 t
(1 row)

显然,默认情况下,对中文是不支持的。

3. PostgreSQL 的数据库全文检索

刚才测试的只是分词,我们用实际的数据库来测试一下。

# 列出所有数据库
\l
# 选择数据库
\c rails365_pro;
select title from articles where to_tsvector('english', body) @@ to_tsquery('english', 'ruby')

输出的结果是这样的。

                        title                        
-----------------------------------------------------
 最简单的用户登录注册系统
 登录认证系统的进阶使用
 用OneAPM作为你的监控平台  
 使用backup来备份数据库
 使用mina来部署ruby on rails应用
 Mina的进阶使用
 用logrotate切割Ruby on rails日志
 用exception_notification结合Slack或数据库来捕获异常
 devise简单入门教程
(9 rows)

上面是搜索了 articles 表中 body 字段,只要包含 ruby 的都找出来。这不是 where like,而是先将 body 分成一个个词,之后再来找的。

再看一个例子。

rails365_pro=# select title from articles where to_tsvector('english', body) @@ to_tsquery('english', 'Mina')
;
              title              
---------------------------------
 使用mina来部署ruby on rails应用
 Mina的进阶使用
(2 rows)

上面是搜索 Mina 这个关键词,两个例子都是用 english 作为语法的,如果搜索中文是搜索不到的。

例如,搜索 title 为 devise 简单入门教程的这篇文章。

rails365_pro=# select title from articles where to_tsvector('english', title) @@ to_tsquery('english', '教程')
;
 title 
-------
(0 rows)

我们把"english"去掉。

rails365_pro=# select title from articles where to_tsvector(title) @@ to_tsquery('教程')
;
 title 
-------
(0 rows)

还是不行。因为没有中文分词器。这个后绪再说。

3. 创建索引

上面的是没有建立索引的情况下操作的,那样肯定不行的,如果数据量大,会很慢。

CREATE INDEX articles_idx ON articles USING gin(to_tsvector('english', body));

具体的操作可以看官方的这篇文章textsearch-tables

完结。

下一篇:PostgreSQL 的全文检索系统之进阶 (二)

本站文章均为原创内容,如需转载请注明出处,谢谢。

0 条回复
暂无回复~~
相关小书
postgresql教程

postgresql教程

postgresql 最全面,最细致的特性介绍与应用教程

发表于

喜欢
统计信息
    学员: 29921
    视频数量: 1996
    文章数量: 526

© 汕尾市求知科技有限公司 | Rails365 Gitlab | 知乎 | b 站 | csdn

粤公网安备 44152102000088号粤公网安备 44152102000088号 | 粤ICP备19038915号

Top