背景

在日常的数据处理中,我们经常会有这样的需求:从一个文本中寻找某个字符串(比如某个单词)。

对这个需求,我们可以用类似这样的SQL完成:SELECT * FROM tbl WHERE text LIKE '%rds PostgreSQL%';(找到含有“rds PostgreSQL”的文本)

现在我们考虑一些特殊的情形:

  1. 需要查找的文本特别多,特别大;
  2. 不做单纯的字符串匹配,而是考虑自然语言的一些特性,比如匹配某一类字符串(域名,人名)或者匹配单词的所有形式(不考虑它的词性及变化,比如have,has,had都匹配出来);
  3. 对中文自然语言特性的支持。

那么此时再用以上的“SELECT ... LIKE ...”就不明智了,因为对数据库来说,这样的SQL必然走的是全表扫描,那么当文本特别多,特别大的时候,查找效率就会很低。

另外,这样的SQL也不会智能到可以处理自然语言的特性。

怎么办呢?PostgreSQL(以下简称PG)提供了强大的全文搜索功能可以满足这样的需求。

对文本的预处理

全文搜索首先需要对文本预处理,包括3步:

  1. 将文本分解成一个个token,这些token可以是数字,单词,域名,人名,email的格式等等。在PG中可以定义一个parser来做这个工作。
  2. 将第一步分解成的token标准化,所谓的标准化就是利用一些规则将token分好类(比如人名是一类,域名是一类等等)。标准化后的token我们称之为lexeme。在PG中是通过定义一个词典来做这个工作。PG里最简单的词典simple的标准化过程就是将大写字母转成小写字母。
  3. 对文本打分,优化查找过程。比如对于待查找的词,文本1匹配的数量大于文本2匹配的数量,那么在这个查找过程,文本1的优先级大于文本2的优先级。

在PG中,以上对文本的预处理可以通过一个函数to_tsvector来完成,函数的返回值是tsvector这个数据类型。

另外,对于待查找的单词,我们也要用to_tsquery这个函数包装起来,函数的返回值是tsquery这个数据类型。

一个简单的例子见下面,to_tsquery里的参数可以使用运算符(&:与,|:或,!:非):

SELECT to_tsvector('fat cats ate fat rats') @@ to_tsquery('fat & rat');?column?
----------t

Quick Start

在了解了这些概念之后,我们用实际的例子来玩一玩PG的全文搜索。

我们在client端输入以下命令,dFp显示的是所有的parser,这里只有一个默认parser(default)。

dFp+ default 显示默认parser(default)的详细信息:parse的过程(5个函数),parse的Token类型(asciihword, asciiword...)。

sbtest=# \dFpList of text search parsersSchema   |  Name   |     Description
------------+---------+---------------------pg_catalog | default | default word parser
(1 row)sbtest=# \dFp+ defaultText search parser "pg_catalog.default"Method      |    Function    | Description
-----------------+----------------+-------------Start parse     | prsd_start     | (internal)Get next token  | prsd_nexttoken | (internal)End parse       | prsd_end       | (internal)Get headline    | prsd_headline  | (internal)Get token types | prsd_lextype   | (internal)Token types for parser "pg_catalog.default"Token name    |               Description
-----------------+------------------------------------------asciihword      | Hyphenated word, all ASCIIasciiword       | Word, all ASCIIblank           | Space symbolsemail           | Email addressentity          | XML entityfile            | File or path namefloat           | Decimal notationhost            | Hosthword           | Hyphenated word, all lettershword_asciipart | Hyphenated word part, all ASCIIhword_numpart   | Hyphenated word part, letters and digitshword_part      | Hyphenated word part, all lettersint             | Signed integernumhword        | Hyphenated word, letters and digitsnumword         | Word, letters and digitsprotocol        | Protocol headsfloat          | Scientific notationtag             | XML taguint            | Unsigned integerurl             | URLurl_path        | URL pathversion         | Version numberword            | Word, all letters
(23 rows)

输入dF+ english,给出标准化各类英语token时所用到的dictionary:

sbtest=# \dF+ english
Text search configuration "pg_catalog.english"
Parser: "pg_catalog.default"Token      | Dictionaries
-----------------+--------------asciihword      | english_stemasciiword       | english_stememail           | simplefile            | simplefloat           | simplehost            | simplehword           | english_stemhword_asciipart | english_stemhword_numpart   | simplehword_part      | english_stemint             | simplenumhword        | simplenumword         | simplesfloat          | simpleuint            | simpleurl             | simpleurl_path        | simpleversion         | simpleword            | english_stem

创建以default为parser的配置defcfg,并增加token映射,这里我们只关心email, url, host:

sbtest=# CREATE TEXT SEARCH CONFIGURATION defcfg (PARSER = default);
CREATE TEXT SEARCH CONFIGURATION
sbtest=# ALTER TEXT SEARCH CONFIGURATION defcfg ADD MAPPING FOR email,url,host WITH simple;
ALTER TEXT SEARCH CONFIGURATION

建好配置defcfg后,我们看看利用defcfg对文本进行处理的结果。这里使用to_tsvector函数,可以看到email,url,host都被识别出来了:

sbtest=# select to_tsvector('defcfg','xxx yyy xxx@taobao.com yyy@sina.com http://google.com/123 12345 ');to_tsvector
-----------------------------------------------------------------------'google.com':4 'google.com/123':3 'xxx@taobao.com':1 'yyy@sina.com':2
(1 row)

在实际对表内的文本做全文搜索时,一般对目标列建立gin索引(也就是倒排索引,详情见官方文档),这样可以加快查询效率,具体操作如下:

sbtest=# CREATE TABLE t1(c1 text);
CREATE TABLE
sbtest=# CREATE INDEX c1_idx ON t1 USING gin(to_tsvector('defcfg', c1));
CREATE INDEX
sbtest=# \d t1Table "public.t1"Column | Type | Modifiers
--------+------+-----------c1     | text |
Indexes:"c1_idx" gin (to_tsvector('defcfg'::regconfig, c1))

这里我们插入2条文本,并做一些匹配:

sbtest=# INSERT INTO t1 VALUES('xxx yyy xxx@taobao.com yyy@sina.com http://google.com 12345');
INSERT 0 1
sbtest=# INSERT INTO t1 VALUES('xxx yyy xxx@gmail.com yyy@sina.com http://google.com 12345');
INSERT 0 1
sbtest=# select * from t1;c1
-------------------------------------------------------------xxx yyy xxx@taobao.com yyy@sina.com http://google.com 12345xxx yyy xxx@gmail.com yyy@sina.com http://google.com 12345
(2 rows)sbtest=# select * from t1 where to_tsvector('defcfg',c1) @@ 'google.com';c1
-------------------------------------------------------------xxx yyy xxx@taobao.com yyy@sina.com http://google.com 12345xxx yyy xxx@gmail.com yyy@sina.com http://google.com 12345
(2 rows)sbtest=# select * from t1 where to_tsvector('defcfg',c1) @@ to_tsquery('google.com & yyy@sina.com');c1
-------------------------------------------------------------xxx yyy xxx@taobao.com yyy@sina.com http://google.com 12345xxx yyy xxx@gmail.com yyy@sina.com http://google.com 12345
(2 rows)sbtest=# select * from t1 where to_tsvector('defcfg',c1) @@ to_tsquery('google.com & xxx@gmail.com');c1
------------------------------------------------------------xxx yyy xxx@gmail.com yyy@sina.com http://google.com 12345
(1 row)

以上的操作都是针对英文,实际上对中文也是支持的,不过会稍微麻烦点,因为中文的token必须通过分词才能产生,所以需要先装分词的组件scws和zhparser,具体可以参考这篇博文。

结语

本文对PG的全文搜索做了一个入门级的介绍,方便用户快速上手,如果需要对全文搜索作更深入的研究,建议阅读官方文档第12章。

PostgreSQL · 特性介绍 · 全文搜索介绍相关推荐

  1. PostgreSQL SQL 语言:全文搜索

    本文档为PostgreSQL 9.6.0文档,本转载已得到原译者彭煜玮授权. 1. 介绍 全文搜索(或者文本搜索)提供了确定满足一个查询的自然语言文档的能力,并可以选择将它们按照与查询的相关度排序.最 ...

  2. Cloud Studio全文搜索功能介绍

    使用全文搜索功能可以在整个项目文件中进行关键字搜索.点击左侧的搜索按钮,或者使用快捷键 cmd+shift+f(Windows 下是 cmd+shift+f),就可以打开全文搜索面板. 输入关键词回车 ...

  3. mysql against 中文_「against的用法」Mysql全文搜索之MATCH...AGAINST的用法介绍 - seo实验室...

    against的用法 前提:mysql只支持英文内容的全文索引,所以只考虑英文的全文搜索.假定数据表名为post,有三列:id.title.content.id是自增长序号,title是varchar ...

  4. Mysql全文搜索之MATCH...AGAINST的用法介绍

    前提:mysql只支持英文内容的全文索引,所以只考虑英文的全文搜索.假定数据表名为post,有三列:id.title.content.id是自增长序号,title是varchar,content是te ...

  5. ES(ElasticSearch)分布式全文搜索引擎介绍及使用方式

    1.什么是ES **ES** 全称 **ElasticSearch** 是一种分布式全文搜索引擎,基于Lucene(全文搜索框架)开发而来. Lucene是公认的迄今为止的最好用的搜索引擎库,但是他所 ...

  6. 搜索介绍 | 当你搜索时,发生了什么?

    全文目录如下: 一如"万物皆可百度"."万物无难事,只要肯百度"所言,搜索在我们生活中早已成为习以为常的事情.毕业季的我们会在每日99+的群聊信息中搜索所需的信 ...

  7. PostgreSQL 10.1 手册_部分 II. SQL 语言_第 12 章 全文搜索_12.9. GIN 和 GiST 索引类型

    12.9. GIN 和 GiST 索引类型 有两种索引可以被用来加速全文搜索.注意全文搜索并非一定需要索引,但是在一个定期会被搜索的列上,通常需要有一个索引. CREATE INDEX name ON ...

  8. linux下软件发布,Linux Kernel 5.12发布下载,附新特性及新功能介绍

    Linus Torvalds在Linux内核邮件列表中宣布正式发布Linux Kernel 5.12版本,已提供linux-5.12.tar.xz/tar.gz下载,以下为你介绍该版本的更改.新特性及 ...

  9. 指尖江湖李忘生鸿蒙初开,剑网3指尖江湖李忘生怎么样_李忘生装备搭配、技能特性、解锁方法介绍_游戏吧...

    李忘生现任纯阳掌教,纯阳五子之首,道号"玉虚子".下面游戏吧小编将为大家带来了李忘生装备属性.技能特性.解锁方法介绍,快来了解一下吧! 解锁方法 获取方法:通过提升和他的好感度获取 ...

最新文章

  1. scrum看板工具做问题跟踪
  2. leetcode @38报数-js
  3. 一堂如何提高代码质量的培训课【转】
  4. 如何让.net程序自动运行在管理员权限下
  5. WinSCP+PuTTY搭配使用 ,解决Windows连接Linux系统文件传输和终端登陆
  6. python计算每月工资多少钱_[Python]CCF——工资计算(201612-2)
  7. 微博技术专家陈波:百亿级访问量的应用如何做缓存架构设计
  8. 特斯拉股价周一大跌8.55% 市值缩水640亿美元
  9. 第二场周赛(递归递推个人Rank赛)——题解
  10. 逍遥android模拟器设置,逍遥安卓模拟器最佳设置电脑上玩手游流畅不卡多开更好用...
  11. Hadoop3——集群搭建以及初体验
  12. timeSetEvent的用法(一)
  13. 机器学习、神经网络、深度学习的关系
  14. 计算机课的十个小游戏制作教程,腾讯内容开放平台
  15. [02/Dec/2019:12:59:10 +0800]之日期转换
  16. 中国开发者将迎来黄金十年
  17. 女大学生王婷婷致信给网上春光照女主角
  18. 关于千牛移动端纯H5插件和QAP应用中H5页面的概念
  19. Ubuntu下解压rar文件的方法
  20. Shellshock 破壳漏洞(CVE-2014-6271)

热门文章

  1. linux命令重定向、、 1、 2、 1、 2、
  2. vector 对某个下标排序_Python实现堆排序
  3. python词云cannot open resource_centos flask验证码pil提示OSError: cannot open resource,问题解决方法...
  4. python如何使用sdk_七牛云存储Python SDK使用教程 - 基本介绍
  5. oracle中rac是什么意思,Oracle中HA、RAC、Datagurad区别
  6. 人力资源管理4个过程及相关重点
  7. Linux定制登录欢迎语
  8. Openlayers中使用Cluster+Overlay实现点击单个要素和聚合要素时显示不同弹窗
  9. 信息系统项目管理师-合同法、招投标法、政府采购法、著作权法考点笔记
  10. MyBatis中提示:Invalid Bound statemnet(not found )com.