12.4. 额外特性

12.4.1. 操纵文档12.4.2. 操纵查询12.4.3. 用于自动更新的触发器12.4.4. 收集文档统计数据

这一节描述在文本搜索中有用的一些额外的函数和操作符。

12.4.1. 操纵文档

第 12.3.1 节展示了未经处理的文本文档如何被转换成tsvector值。PostgreSQL也提供了用于操纵已经为tsvector形式的文档的函数和操作符。

tsvector || tsvector

tsvector连接操作符返回一个向量,它结合了作为参数给出的两个向量的词位和位置信息。位置和权重标签在连接期间被保留。出现在右手向量中的位置被使用左手向量中提到的最大位置进行偏移,这样结果几乎等于在两个原始文档字符串的连接上执行to_tsvector的结果(这种等价不是完全的,因为从左手参数的尾端移除的任何停用词将会影响结果,而如果文本连接被使用它们就影响了右手参数中的词位位置)。

使用向量形式的连接而不是在应用to_tsvector之前连接文本的一个优点是你可以使用不同配置来解析文档的不同小节。此外,因为setweight函数按照相同的方式标记给定向量的所有词位,如果你想把文档的不同部分标注不同的权重,你就有必要解析文本并且在连接之前做setweight

setweight(vector tsvectorweight "char") returns tsvector

setweight返回输入向量的一个拷贝,其中每一个位置都被标注为给定的权重ABCDD是新向量的默认值并且并不会被显示在输出上)。向量被连接时会保留这些标签,允许来自文档的不同部分的词被排名函数给予不同的权重。

注意权重标签是应用到位置而不是词位。如果输入向量已经被剥离了位置,则setweight什么也不会做。

length(vector tsvector) returns integer

返回存储在向量中的词位数。

strip(vector tsvector) returns tsvector

返回一个向量,其中列出了和给定向量相同的词位,不过没有任何位置或者权重信息。其结果通常比未被剥离的向量小很多,但是用处也小很多。和未被剥离的向量一样,相关度排名在已剥离的向量上也不起作用。此外,<->(FOLLOWED BY)tsquery操作符不会匹配已剥离的输入,因为它无法确定词位之间的距离。

表 9.41中有tsvector相关函数的完整列表。

12.4.2. 操纵查询

第 12.3.2 节展示了未经处理的文本形式的查询如何被转换成tsquery值。PostgreSQL也提供了用于操纵已经是tsquery形式的查询的函数和操作符。

tsquery && tsquery

返回用 AND 结合的两个给定查询。

tsquery || tsquery

返回用 OR 结合的两个给定查询。

!! tsquery

返回一个给定查询的反(NOT)。

tsquery <-> tsquery

返回一个查询,它用<->(FOLLOWED BY)tsquery操作符搜索两个紧跟的匹配,第一个匹配符合第一个给定的查询而第二个匹配符合第二个给定的查询。例如:

SELECT to_tsquery('fat') <-> to_tsquery('cat | rat');?column?
-----------------------------------'fat' <-> 'cat' | 'fat' <-> 'rat'
tsquery_phrase(query1 tsqueryquery2 tsquery [, distance integer ]) returns tsquery

返回一个查询,它使用<N> tsquery操作符搜索两个距离为distance个词位的匹配,第一个匹配符合第一个给定的查询而第二个匹配符合第二个给定的查询。例如:

SELECT tsquery_phrase(to_tsquery('fat'), to_tsquery('cat'), 10);tsquery_phrase
------------------'fat' <10> 'cat'
numnode(query tsquery) returns integer

返回一个tsquery中的结点数(词位外加操作符)。要确定查询是否有意义或者是否只包含停用词时,这个函数有用,在前一种情况它返回 > 0,后一种情况返回 0。例子:

SELECT numnode(plainto_tsquery('the any'));
NOTICE:  query contains only stopword(s) or doesn't contain lexeme(s), ignorednumnode
---------0SELECT numnode('foo & bar'::tsquery);numnode
---------3
querytree(query tsquery) returns text

返回一个tsquery中可以被用来搜索一个索引的部分。这个函数可用来检测不可被索引的查询,例如那些只包含停用词或者只有否定术语的查询。例如:

SELECT querytree(to_tsquery('!defined'));querytree
-----------

12.4.2.1. 查询重写

ts_rewrite函数族在一个给定的tsquery中搜索一个目标子查询的出现,并且将每一次出现替换成一个替补子查询。本质上这个操作就是一个tsquery版本的子串替换。一个目标和替补的组合可以被看成是一个查询重写规则。一个这类重写规则的集合可以是一个强大的搜索助手。例如,你可以使用同义词扩展搜索(如,new yorkbig applenycgotham),或者收缩搜索来将用户导向某些特点主题。在这个特性和分类词典(第 12.6.4 节)有些功能重叠。但是,你可以随时修改一组重写规则而无需重索引,而更新一个分类词典则要求进行重索引才能生效。

ts_rewrite (query tsquerytarget tsquerysubstitute tsquery) returns tsquery

这种形式的ts_rewrite简单地应用一个单一重写规则:不管target出现在query中的那个地方,它都被substitute替代。例如:

SELECT ts_rewrite('a & b'::tsquery, 'a'::tsquery, 'c'::tsquery);ts_rewrite
------------'b' & 'c'
ts_rewrite (query tsqueryselect text) returns tsquery

这种形式的ts_rewrite接受一个开始query和一个 SQL select命令,它们以一个文本字符串的形式给出。select必须得到tsquery类型的两列。对于select结果的每一行,在当前query值中出现的第一列值(目标)被第二列值(替补)所替换。例如:

CREATE TABLE aliases (t tsquery PRIMARY KEY, s tsquery);
INSERT INTO aliases VALUES('a', 'c');SELECT ts_rewrite('a & b'::tsquery, 'SELECT t,s FROM aliases');ts_rewrite
------------'b' & 'c'

注意当多个重写规则被以这种方式应用时,应用的顺序很重要;因此在实际中你会要求源查询按某些排序键ORDER BY

让我们考虑一个现实的天文学例子。我们将使用表驱动的重写规则扩展查询supernovae

CREATE TABLE aliases (t tsquery primary key, s tsquery);
INSERT INTO aliases VALUES(to_tsquery('supernovae'), to_tsquery('supernovae|sn'));SELECT ts_rewrite(to_tsquery('supernovae & crab'), 'SELECT * FROM aliases');ts_rewrite
---------------------------------'crab' & ( 'supernova' | 'sn' )

我们可以通过只更新表来改变重写规则:

UPDATE aliases
SET s = to_tsquery('supernovae|sn & !nebulae')
WHERE t = to_tsquery('supernovae');SELECT ts_rewrite(to_tsquery('supernovae & crab'), 'SELECT * FROM aliases');ts_rewrite
---------------------------------------------'crab' & ( 'supernova' | 'sn' & !'nebula' )

当有很多重写规则时,重写可能会很慢,因为它要为为每一个可能的匹配检查每一条规则。要过滤掉明显不符合的规则,我们可以为tsquery类型使用包含操作符。在下面的例子中,我们只选择那些可能匹配原始查询的规则:

SELECT ts_rewrite('a & b'::tsquery,'SELECT t,s FROM aliases WHERE ''a & b''::tsquery @> t');ts_rewrite
------------'b' & 'c'

12.4.3. 用于自动更新的触发器

当使用一个单独的列来存储你的文档的tsvector表示时,有必要创建一个触发器在文档内容列改变时更新tsvector列。两个内建触发器函数可以用于这个目的,或者你可以编写你自己的触发器函数。

tsvector_update_trigger(tsvector_column_name, config_name, text_column_name [, ... ])
tsvector_update_trigger_column(tsvector_column_name, config_column_name, text_column_name [, ... ])

这些触发器函数在CREATE TRIGGER命令中指定的参数控制下,自动从一个或多个文本列计算一个tsvector列。它们使用的一个例子是:

CREATE TABLE messages (title       text,body        text,tsv         tsvector
);CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE
ON messages FOR EACH ROW EXECUTE PROCEDURE
tsvector_update_trigger(tsv, 'pg_catalog.english', title, body);INSERT INTO messages VALUES('title here', 'the body text is here');SELECT * FROM messages;title    |         body          |            tsv
------------+-----------------------+----------------------------title here | the body text is here | 'bodi':4 'text':5 'titl':1SELECT title, body FROM messages WHERE tsv @@ to_tsquery('title & body');title    |         body
------------+-----------------------title here | the body text is here

在创建了这个触发器后,在titlebody中的任何修改将自动地被反映到tsv中,不需要应用来操心同步的问题。

第一个触发器参数必须是要被更新的tsvector列的名字。第二个参数指定要被用来执行转换的文本搜索配置。对于tsvector_update_trigger,配置名被简单地用第二个触发器参数给出。如上所示,它必须是模式限定的,因此该触发器行为不会因为search_path中的改变而改变。对于tsvector_update_trigger_column,第二个触发器参数是另一个表列的名称,它必须是类型regconfig。这允许做一种逐行的配置选择。剩下的参数是文本列的名称(类型为textvarcharchar)。它们将按给定的顺序被包括在文档中。NULL 值将被跳过(但是其他列仍将被索引)。

这些内建触发器的一个限制是它们将所有输入列同样对待。要对列进行不同的处理 — 例如,使标题的权重和正文的不同 — 就需要编写一个自定义触发器。下面是用PL/pgSQL作为触发器语言的一个例子:

CREATE FUNCTION messages_trigger() RETURNS trigger AS $$
beginnew.tsv :=setweight(to_tsvector('pg_catalog.english', coalesce(new.title,'')), 'A') ||setweight(to_tsvector('pg_catalog.english', coalesce(new.body,'')), 'D');return new;
end
$$ LANGUAGE plpgsql;CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATEON messages FOR EACH ROW EXECUTE PROCEDURE messages_trigger();

记住当在触发器内创建tsvector值时,显式地指定配置名非常重要,这样列的内容才不会被default_text_search_config的改变所影响。如果不这样做很可能导致问题,例如在转储并重新载入之后搜索结果改变。

12.4.4. 收集文档统计数据

ts_stat被用于检查你的配置以及寻找候选的停用词。

ts_stat(sqlquery text, [ weights text, ]OUT word text, OUT ndoc integer,OUT nentry integer) returns setof record

sqlquery是一个文本值,它包含一个必须返回单一tsvector列的 SQL 查询。ts_stat执行该查询并返回有关包含在该tsvector数据中的每一个可区分词位(词)的统计数据。返回的列是:

  • word text — 一个词位的值

  • ndoc integer — 词出现过的文档(tsvector)的数量

  • nentry integer — 词出现的总次数

如果提供了权重,只有具有其中之一权重的出现才被计算在内。

例如,要在一个文档集合中查找十个最频繁的词:

SELECT * FROM ts_stat('SELECT vector FROM apod')
ORDER BY nentry DESC, ndoc DESC, word
LIMIT 10;

同样的要求,但是只计算以权重AB出现的次数:

SELECT * FROM ts_stat('SELECT vector FROM apod', 'ab')
ORDER BY nentry DESC, ndoc DESC, word
LIMIT 10;

本文转自PostgreSQL中文社区,原文链接:12.4. 额外特性

PostgreSQL 10.1 手册_部分 II. SQL 语言_第 12 章 全文搜索_12.4. 额外特性相关推荐

  1. PostgreSQL 10.1 手册_部分 II. SQL 语言_第 9 章 函数和操作符_9.23. 行和数组比较

    9.23. 行和数组比较 9.23.1. IN9.23.2. NOT IN9.23.3. ANY/SOME (array)9.23.4. ALL (array)9.23.5. 行构造器比较9.23.6 ...

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

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

  3. PostgreSQL 10.1 手册_部分 II. SQL 语言_第 9 章 函数和操作符_9.4. 字符串函数和操作符...

    9.4. 字符串函数和操作符 9.4.1. format 本节描述了用于检查和操作字符串值的函数和操作符.在这个环境中的串包括所有类型character.character varying和text的 ...

  4. PostgreSQL 10.1 手册_部分 II. SQL 语言_第 8 章 数据类型_8.10. 位串类型

    8.10. 位串类型 位串就是一串 1 和 0 的串.它们可以用于存储和可视化位掩码.我们有两种类型的 SQL 位类型:bit(n)和bit varying(n),其中 n是一个正整数. bit类型的 ...

  5. PostgreSQL 10.1 手册_部分 II. SQL 语言_第 5 章 数据定义_5.11. 外部数据

    5.11. 外部数据 PostgreSQL实现了部分的SQL/MED规定,允许我们使用普通SQL查询来访问位于PostgreSQL之外的数据.这种数据被称为外部数据(注意这种用法不要和外键混淆,后者是 ...

  6. PostgreSQL 10.1 手册_部分 II. SQL 语言_第 9 章 函数和操作符_9.15. JSON 函数和操作符...

    9.15. JSON 函数和操作符 表 9.43展示了可以用于两种 JSON 数据类型(见第 8.14 节)的操作符. 表 9.43. json和jsonb 操作符 操作符 右操作数类型 描述 例子 ...

  7. PostgreSQL 10.1 手册_部分 II. SQL 语言_第 10 章 类型转换_10.4. 值存储

    10.4. 值存储 将被插入到一个表的值会按照下列步骤被转换到目标列的数据类型. 值存储类型转换 检查一个与目标的准确匹配. 否则,尝试转换表达式为目标类型.如果在两种类型之间的一个 赋值造型已经被注 ...

  8. PostgreSQL 10.1 手册_部分 II. SQL 语言_第 8 章 数据类型_8.6. 布尔类型

    8.6. 布尔类型 PostgreSQL提供标准的SQL类型boolean,参见表 8.19.boolean可以有多个状态:"true(真)"."false(假)&quo ...

  9. PostgreSQL 10.1 手册_部分 II. SQL 语言_第 5 章 数据定义_5.5. 修改表

    5.5. 修改表 5.5.1. 增加列5.5.2. 移除列5.5.3. 增加约束5.5.4. 移除约束5.5.5. 更改列的默认值5.5.6. 修改列的数据类型5.5.7. 重命名列5.5.8. 重命 ...

最新文章

  1. 30个流行的jQuery Plugins
  2. linux who命令实现,linux下 who命令(3)(示例代码)
  3. ASP.NET之纠错
  4. 趣学python3(48)--列出所有目录及子目录文件
  5. JavaScript上传图片及时预览
  6. golang-gui编程
  7. azure api 管理_Azure Cosmos DB和MongoDB API入门
  8. 中国专业开发者最多,最受 Web 服务青睐,Java 8 为最受欢迎版本 | 2020 年 Java 开发现状大调查...
  9. npm修改全局包安装路径
  10. Python源码深度解析—对象的创建
  11. Java类加载机制与反射 jvm学习
  12. java lcs矩阵,LCS算法的两种JAVA实现方式
  13. 电脑参数,台式电脑怎么查看配置参数|如何查询台式机硬件配置
  14. OPENCV函数介绍:normalize()
  15. JZOJ100047. 【NOIP2017提高A组模拟7.14】基因变异
  16. java实现京东云第三方登录
  17. alt tab无法切换窗口
  18. 计算机错误651是什么故障,宽带连接错误显示代码651是什么原因 宽带连接错误651的解决方法...
  19. MapReduce基本概述——分布式计算框架
  20. c程序设计语言k rpdf,《C程序设计语言》(KR)中文高清非扫描件

热门文章

  1. android封装aidl接口,Android远端接口AIDL及服务回调用法
  2. Docker 容器使用
  3. keil C51 例子
  4. VS2015新建项目无法选择framework 4.6.2
  5. ListView添加headview
  6. ACM题目————A simple problem
  7. 光棍节的快乐 NYOJ 451
  8. js 简单的滑动教程(四)
  9. (转自ztp800201) Android - 自定义标题栏(在标题栏中增加按钮和文本居中)
  10. Python利用PyPDF2库获取PDF文件总页码