1. 全文检索

    1. 概述

文本搜索(~、~*、LIKE和ILIKE操作符)在对文本进行搜索操作时,缺少一些系统要求的必要属性:

  1. 及时是英文环境也没有语义支持;

由于要识别派生词并不是那么容易,因此正则表达式也不能满足要求。如,satisfies和satisfy,当使用正则表达式寻找satisfy时,并不会查询到包含satisfies的文档。用户可以使用OR搜索多种派生形式,但过程非常繁琐。并且有些词会有上千的派生词,因此容易出错。

  1. 没有对搜索结果的分类(排序)。当搜索出成千的文档时,查找效率很低。
  2. 由于没有索引的支持,每一次的搜索需要遍历所有的文档,整体搜索比较缓慢。

使用全文索引可以对文档进行预处理,并且可以使后续的搜索更快速。预处理过程包括:

  1. 将文档解析成记号:

为每个文档标记不同类别的记号是非常有必要的,例如:数字、文字、复合词、电子邮件地址,这样就可以做不同的处理。原则记号的类别依赖于具体的应用,但对于大多数的应用来说,可以使用一组预定义的记号类。

  1. 将记号转换为词位:

词位像记号一样是一个字符串,但它已经标准化处理,这样同一个词的不同形式是一样的。例如,标准化通常包括:将大写字母折成小写字母、删除后缀(如英语中的s或者es)。这将允许通过搜索找到同一个词的不同形式,不需要繁琐地输入所有可能的变形样式。同时,这一步通常会删除停用词。这些停用词通常因为太常见而对搜索无用。(总之,记号是文档文本的原片段,而词位被认为是有用的索引和搜索词。)GBase 8c使用词典执行这一步,且提供了各种标准的词典。

  1. 保存搜索优化后的预处理文档。

比如,每个文档可以呈现为标准化词位的有序组合。伴随词位,通常还需要存储词位位置信息以用于邻近排序。因此文档包含的查询词越密集其排序越高。

词典能够对词位如何标准化做到细粒度控制。使用合适的词典,可以定义不被索引的停用词。

数据类型tsvector用于存储预处理文档,tsquery用于存储查询条件,详细请参见控制文本搜索。为这些数据类型提供的函数和操作符请参见函数和操作符。其中最重要的是匹配运算符@@,将在基本文本匹配中介绍。

  1. 文档概念

文档是全文搜索系统的搜索单元,例如:杂志上的一篇文章或电子邮件消息。文本搜索引擎必须能够解析文档,而且可以存储父文档的关联词素(关键词)。后续,这些关联词位用来搜索包含查询词的文档。

文档通常是一个数据库表中一行的文本字段,或者这些字段的可能组合(级联)。文档可能存储在多个表中或者需动态获取。换句话说,一个文档由被索引化的不同部分构成,因此无法存储为一个整体。比如:

gbase=# SELECT name || ' ' ||  age || ' ' ||  address || ' ' || salary AS document FROM company WHERE id = 2;

document

----------------------

Allen 25 Texas 15000

(1 row)

注意:实际上,在这些示例查询中,应该使用coalesce防止一个独立的NULL属性导致整个文档的NULL结果。

另外一种可能是:文档在文件系统中作为简单的文本文件存储。在这种情况下,数据库可以用于存储全文索引并且执行搜索,同时可以使用一些唯一标识从文件系统中检索文档。然而,从数据库外部检索文件需要拥有系统管理员权限或者特殊函数支持。因此,还是将所有数据保存在数据库中比较方便。同时,将所有数据保存在数据库中可以方便地访问文档元数据以便于索引和显示。

为了实现文本搜索目的,必须将每个文档减少至预处理后的tsvector格式。搜索和相关性排序都是在tsvector形式的文档上执行的。原始文档只有在被选中要呈现给用户时才会被当检索。因此,我们常将tsvector说成文档,但是很显然其实它只是完整文档的一种紧凑表示。

  1. 基本文本匹配

GBase 8c的全文搜索基于匹配操作符@@,它在一个tsvector(文档)匹配一个tsquery(查询)时返回true。例如:

gbase=# SELECT 'a fat cat sat on a mat and ate a fat rat'::tsvector @@ 'cat & rat'::tsquery;

?column?

----------

t

(1 row)

gbase=# SELECT 'fat & cow'::tsquery @@ 'a fat cat sat on a mat and ate a fat rat'::tsvector;

?column?

----------

f

(1 row)

tsquery可以包含搜索术语,并且可以使用 AND 、OR、NOT 以及 FOLLOWED BY 操作符结合多个术语。函数to_tsquery、plainto_tsquery以及phraseto_tsquery可用于将用户书写的文本转换为正确的tsquery。文本搜索匹配:

gbase=# SELECT to_tsvector('fat cats ate fat rats') @@ to_tsquery('fat & rat');

?column?

----------

f

(1 row)

@@操作符也支持text输出,它允许在简单情况下跳过从文本字符串到tsvector或tsquery的显式转换。可用形式有:

tsvector @@ tsquery

tsquery  @@ tsvector

text @@ tsquery

text @@ text

形式text @@ tsquery等价于to_tsvector(x) @@ y。形式text @@ text等价于to_tsvector(x) @@ plainto_tsquery(y)。

在<->(FOLLOWED BY) tsquery操作符的帮助下搜索可能的短语,只有该操作符的参数的匹配是相邻的并且符合给定顺序时,该操作符才算是匹配。例如:

gbase=# SELECT to_tsvector('fatal error') @@ to_tsquery('fatal <-> error');

?column?

----------

t

(1 row)

gbase=# SELECT to_tsvector('error is not fatal') @@ to_tsquery('fatal <-> error');

?column?

----------

f

(1 row)

FOLLOWED BY 操作符还有一种更一般的版本,形式是<N>,其中N是一个表示匹配词位位置之间的差。<1>和<->相同,而<2>允许刚好一个其他词位出现在匹配之间,以此类推。当有些词是停用词时,phraseto_tsquery函数利用这个操作符来构造一个能够匹配多词短语的tsquery。例如:

gbase=# SELECT phraseto_tsquery('cats ate rats');

phraseto_tsquery

-----------------------------

'cats' <-> 'ate' <-> 'rats'

(1 row)

gbase=# SELECT phraseto_tsquery('the cats ate the rats');

phraseto_tsquery

-------------------------------------------------

'the' <-> 'cats' <-> 'ate' <-> 'the' <-> 'rats'

(1 row)

<0>可以被用来要求两个匹配同一个词的模式。

圆括号可以被用来控制tsquery操作符的嵌套。如果没有圆括号,|的计算优先级最低,然后从低到高依次是&、<->、!。

  1. 配置

全文检索功能还可以做更多事情:忽略索引某个词(停用词),处理同义词和使用复杂解析,例如:不仅基于空格的解析。这些功能通过文本搜索分词器控制。GBase 8c支持多语言的预定义的分词器,并且可以创建分词器(gsql的\dF命令显示了所有可用分词器)。

在安装期间选择一个合适的分词器,并且在postgresql.conf中相应的设置default_text_search_config。如果为了整个集群使用同一个文本搜索分词器可以使用postgresql.conf中的值。如果需要在集群中使用不同分词器,可以使用ALTER DATABASE ... SET在任一数据库进行配置。用户也可以在每个会话中设置default_text_search_config。

每个依赖于分词器的文本搜索函数有一个可选的配置参数,用以明确声明所使用的分词器。仅当忽略这个参数的时候,才使用default_text_search_config。

为了更方便的建立自定义文本搜索分词器,可以通过简单的数据库对象建立分词器。GBase 8c文本搜索功能提供了四种类型与分词器相关的数据库对象:

  1. 文本搜索解析器将文档分解为词位,并且分类每个词位(例如:词和数字)。
  2. 文本搜索词典将词位转换成规范格式并且丢弃停用词。
  3. 文本搜索模板提供潜在的词典功能:一个词典指定一个模板,并且为模板设置参数。
  4. 文本搜索分词器选择一个解析器,并且使用一系列词典规范化语法分析器产生的词位。
    1. 表和索引

      1. 搜索一个表

在没有索引的情况下的全文检索:查询文档中每行title匹配friend:

gbase=# SELECT * FROM pgweb;

id |                                                                                     body                                                                                     |   title   | last_mod_date

----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------+---------------

3 | England is a country that is part of the United Kingdom. It shares land borders with Scotland to the north and Wales to the west.                                            | England   | 2010-01-01

5 | Russia, also officially known as the Russian Federation, is a sovereign state in northern Eurasia.                                                                           | Russia    | 2010-01-01

1 | China, officially the People's Republic of China(PRC), located in Asia, is the world's most populous state.                                                                  | China     | 2010-01-01

1 | China, officially the People's Republic of China(PRC), located in Asia, is the world's most populous state.                                                                  | China     | 2010-01-01

4 | Australia, officially the Commonwealth of Australia, is a country comprising the mainland of the Australian continent, the island of Tasmania, and numerous smaller islands. | Australia | 2010-01-01

8 | France, is a sovereign state comprising territory in western Europe and several overseas regions and territories.                                                            | France    | 2010-01-01

9 | Italy officially the Italian Republic, is a unitary parliamentary republic in Europe.                                                                                        | Italy     | 2010-01-01

10 | India, officially the Republic of India, is a country in South Asia.                                                                                                         | India     | 2010-01-01

13 | Mexico, officially the United Mexican States, is a federal republic in the southern part of North America.                                                                   | Mexico    | 2010-01-01

2 | America is a rock band, formed in England in 1970 by multi-instrumentalists Dewey Bunnell, Dan Peek, and Gerry Beckley.                                                      | America   | 2010-01-01

6 | Japan is an island country in East Asia.                                                                                                                                     | Japan     | 2010-01-01

7 | Germany, officially the Federal Republic of Germany, is a sovereign state and federal parliamentary republic in central-western Europe.                                      | Germany   | 2010-01-01

11 | Brazil, officially the Federative Republic of Brazil,is the largest country in both South America and Latin America.                                                         | Brazil    | 2010-01-01

12 | Canada is a country in the northern half of North America.                                                                                                                   | Canada    | 2010-01-01

(14 rows)

gbase=# SELECT id, body, title FROM pgweb WHERE to_tsvector('english', body) @@to_tsquery('english', 'america');

id |                                                          body                                                           |  title

----+-------------------------------------------------------------------------------------------------------------------------+---------

13 | Mexico, officially the United Mexican States, is a federal republic in the southern part of North America.              | Mexico

2 | America is a rock band, formed in England in 1970 by multi-instrumentalists Dewey Bunnell, Dan Peek, and Gerry Beckley. | America

11 | Brazil, officially the Federative Republic of Brazil,is the largest country in both South America and Latin America.    | Brazil

12 | Canada is a country in the northern half of North America.                                                              | Canada

(4 rows)

该查询还会返回friends和friendly等类似的结果。

上面的查询指定使用english配置参数。也可以忽略配置参数:

gbase=# SELECT id, body, title FROM pgweb WHERE to_tsvector(body) @@to_tsquery('america');

id |                                                          body                                                           |  title

----+-------------------------------------------------------------------------------------------------------------------------+---------

13 | Mexico, officially the United Mexican States, is a federal republic in the southern part of North America.              | Mexico

2 | America is a rock band, formed in England in 1970 by multi-instrumentalists Dewey Bunnell, Dan Peek, and Gerry Beckley. | America

11 | Brazil, officially the Federative Republic of Brazil,is the largest country in both South America and Latin America.    | Brazil

12 | Canada is a country in the northern half of North America.                                                              | Canada

(4 rows)

这个查询将使用由default_text_search_config设置的配置。

  1. 创建索引

可以创建一个GIN索引来加速文本搜索:

gbase=# CREATE INDEX pgweb_idx ON pgweb USING GIN(to_tsvector('english', body));

CREATE INDEX

to_tsvector()函数有两个版本。只输一个参数的版本和输两个参数的版本。只输一个参数时,系统默认采用default_text_search_config所指定的分词器。

注意:创建索引时必须使用to_tsvector的两参数版本。只有指定了分词器名称的全文检索函数才可以在索引表达式中使用。这是因为索引的内容必须不受default_text_search_config的影响,否则索引内容可能不一致。由于default_text_search_config的值可以随时调整,从而导致不同条目生成的tsvector采用了不同的分词器,并且没有办法区分究竟使用了哪个分词器。正确地转储和恢复这样的索引也是不可能的。

因为在上述创建索引中to_tsvector使用了两个参数,只有当查询时也使用了两个参数,且参数值与索引中相同时,才会使用该索引。也就是说,WHERE to_tsvector('english',body) @@ 'a & b' 可以使用索引,但WHERE to_tsvector(body) @@ 'a & b'不能使用索引。这确保只使用这样的索引——索引各条目是使用相同的分词器创建的。

索引中的分词器名称由另一列指定时可以创建更复杂的表达式索引,例如:

gbase=# CREATE INDEX pgweb_idx_2 ON pgweb USING GIN(to_tsvector(config_name, body));

CREATE INDEX

这里config_name是pgweb表中的一个列。可以在同一个索引中混合配置,同时记录配置所属的索引项。

索引可以连接列:

gbase=# CREATE INDEX pgweb_idx_3 ON pgweb USING GIN(to_tsvector('english', title || ' ' || body));

CREATE INDEX

另一种方法是创建一个单独的tsvector列来保存to_tsvector的输出。这个例子是title和body的连接,使用coalesce来保证当其他域为NULL时一个域仍然能留在索引中:

gbase=# ALTER TABLE pgweb ADD COLUMN textsearchable_index_col tsvector;

ALTER TABLE

gbase=# UPDATE pgweb SET textsearchable_index_col = to_tsvector('english', coalesce(title,'') || ' ' || coalesce(body,''));

UPDATE 14

然后创建一个GIN索引来加速搜索:

gbase=# CREATE INDEX textsearch_idx ON pgweb USING GIN(textsearchable_index_col);

CREATE INDEX

最后执行一个快速的全文检索:

gbase=# SELECT title FROM pgweb WHERE textsearchable_index_col @@ to_tsquery('north & america') ORDER BY last_mod_date DESC LIMIT 10;

title

--------

Canada

Mexico

(2 rows)

在使用一个单独的列来存储tsvector表示时,有必要创建一个触发器在title或body改变时保证tsvector列为当前值。

单独列方法相对于表达式索引的一个优势在于,它不必为了利用索引而在查询中显式地指定文本搜索配置。另一个优势是搜索将会更快,因为它不必重做to_tsvector调用来验证索引匹配。表达式索引方法更容易建立,但是它要求更少的磁盘空间,因为tsvector表示没有被显式地存储下来。

  1. 控制文本搜索

    1. 解析文档

PostgreSQL提供了函数to_tsvector将一个文档转换成tsvector数据类型。

to_tsvector([ config regconfig, ] document text) returns tsvector

to_tsvector把一个文本文档解析成记号,把记号缩减成词位,并且返回一个tsvector,它列出了词位以及词位在文档中的位置。文档被根据指定的或默认的文本搜索配置来处理。下面是一个简单例子:

gbase=# SELECT to_tsvector('english', 'a fat  cat sat on a mat - it ate a fat rats');

to_tsvector

-----------------------------------------------------

'ate':9 'cat':3 'fat':2,11 'mat':7 'rat':12 'sat':4

(1 row)

上面的例子中,作为结果的tsvector不包含词a、on或it,词rats变成了rat,且忽略了标点符号-。

to_tsvector函数在内部调用了一个解析器,把文档文本分解成记号并且为每一种记号分配类型。对于每一个记号,会去查询一个词典列表,该列表会根据记号的类型而变化。第一个识别记号的词典产生一个或多个正规化的词位来表示该记号。例如,rats变成rat是因为一个词典识别到该词rats是rat的复数形式。一些频繁出现的词会被认为是停用词并在搜索中将被忽略,例如上面例子中的a、on和it。词典中查不到的词和记号也会被忽略,如上面例子中的符号-(因为词典中没有空间符号)。要索引的内容类型是由文本搜索配置决定的。同一个数据库可以有多种不同配置,并且有用于多种语言的预定义配置。在上面的例子中使用的是默认配置english。

函数setweight指定tsvector中的项的权重,以A、B、C或D标识。通常用来标记文档不同部分(例如标题、正文),可以用来对搜索结果排序。

因为to_tsvector(NULL) 将返回NULL,coalesce可以在所有返回为null时使用。如下是一个从结构化文档创建tsvector的例子:

gbase=# SELECT * FROM tt;

id | title | keyword | abstract |                                                     body                                                     | ti

----+-------+---------+----------+--------------------------------------------------------------------------------------------------------------+----

1 | China | Beijing | China    | China, officially the People's Republic of China (PRC), located in Asia, is the world's most populous state. |

(1 row)

gbase=# UPDATE tt SET ti =

    setweight(to_tsvector(coalesce(title,'')), 'A')    ||

    setweight(to_tsvector(coalesce(keyword,'')), 'B')  ||

    setweight(to_tsvector(coalesce(abstract,'')), 'C') ||

setweight(to_tsvector(coalesce(body,'')), 'D');

UPDATE 1

这里使用setweight将标注tsvector每个词的来源,并且将标注过的tsvector值用连接操作符||合并起来。

  1. 解析查询

PostgreSQL提供了函数to_tsquery、plainto_tsquery和phraseto_tsquery用来把一个查询转换成tsquery数据类型。to_tsquery提供了比plainto_tsquery和phraseto_tsquery更多的特性,但是它对其输入要求更加严格。

to_tsquery([ config regconfig, ] querytext text) returns tsquery

to_tsquery从querytext创建一个tsquery值,该值由被tsquery操作符&(AND)、|(OR)、!(NOT)和<->(FOLLOWED BY)分隔的单个记号组成。这些操作符可以使用圆括号分组。to_tsquery的输入必须遵循tsquery输入的一般规则。两者的区别在于基本的tsquery输入把记号当作表面值,而to_tsquery 会使用指定的或者默认的配置把每个记号正规化成一个词位,并且丢弃掉任何停用词。例如:

gbase=# SELECT to_tsquery('english', 'The & Fat & Rats');

to_tsquery

---------------

'fat' & 'rat'

(1 row)

和在基本tsquery输入中一样,权重可以被附加到每一个词位来限制它只匹配属于那些权重的tsvector词位。例如:

gbase=# SELECT to_tsquery('english', 'Fat | Rats:AB');

to_tsquery

------------------

'fat' | 'rat':AB

(1 row)

*可以被附加到一个词位来指定前缀匹配:

gbase=# SELECT to_tsquery('supern:*A & star:A*B');

to_tsquery

--------------------------

'supern':*A & 'star':*AB

(1 row)

这样一个词位将匹配一个tsvector中的任意以给定字符串开头的词。

to_tsquery也能够接受单引号短语。当配置包括一个会在这种短语上触发的分类词典时就是它的主要用处。在下面的例子中,一个分类词典含规则supernovae stars : sn:

gbase=# SELECT to_tsquery('''supernovae stars'' & !crab');

to_tsquery

----------------------------------

'supernovae' & 'stars' & !'crab'

(1 row)

在没有引号时,to_tsquery将为那些没有被 AND、OR 或者 FOLLOWED BY 操作符分隔的记号产生一个语法错误。

plainto_tsquery([ config regconfig, ] querytext text) returns tsquery

plainto_tsquery将未格式化的文本querytext转换成一个tsquery值。该文本被解析并被正规化,很像to_tsvector,然后&(AND)布尔操作符被插入到留下来的词之间。例如:

gbase=# SELECT plainto_tsquery('english', 'The Fat Rats');

plainto_tsquery

-----------------

'fat' & 'rat'

(1 row)

注意plainto_tsquery不会识其输入中的tsquery操作符、权重标签或前缀匹配标签:

gbase=# SELECT plainto_tsquery('english', 'The Fat & Rats:C');

plainto_tsquery

---------------------

'fat' & 'rat' & 'c'

(1 row)

这里,所有输入的标点都被作为空间符号并且丢弃。

  1. 排序搜索结果

排序试图针对特定查询衡量文档的相关度,从而将众多的匹配文档中相关度最高的文档排在最前。GBase 8c提供了两个预置的排序函数。函数考虑了词法、距离和结构信息;也就是,他们考虑查询词在文档中出现的频率、紧密程度、以及他们出现的地方在文档中的重要性。然而,相关性的概念是模糊的,并且是跟应用强相关的。不同的应用程序可能需要额外的信息来排序,比如,文档的修改时间,内置的排序函数等。也可以开发自己的排序函数或者采用附加因素组合这些排序函数的结果来满足特定需求。

两个预置的排序函数:

ts_rank([ weights float4[], ] vector tsvector, query tsquery [, normalization integer ]) returns float4

基于向量匹配率对词位进行排序:

ts_rank_cd([ weights float4[], ] vector tsvector, query tsquery [, normalization integer ]) returns float4

该函数需要位置信息的输入。因此它不能在"剥离"tsvector值的情况下运行—它将总是返回零。

对于这两个函数,可选的weights参数提供给词加权重的能力,词的权重大小取决于所加的权值。权重阵列指定在排序时为每类词汇加多大的权重。

{D-权重, C-权重, B-权重, A-权重}

如果没有提供权重,则使用缺省值:{0.1, 0.2, 0.4, 1.0}

通常的权重是用来标记文档特殊领域的词,如标题或最初的摘要,所以相对于文章主体中的词它们有着更高或更低的重要性。

由于较长的文档有更多的机会包含查询词,因此有必要考虑文档的大小。例如,包含有5个搜索词的一百字文档比包含有5个搜索词的一千字文档相关性更高。两个预置的排序函数都采用了一个整型的标准化选项来定义文档长度是否影响排序及如何影响。这个整型选项控制多个行为,所以它是一个屏蔽字:可以使用|指定一个或多个行为(例如,2|4)。

  1. 0(缺省)表示:跟长度大小没有关系
  2. 1 表示:排名(rank)除以(文档长度的对数+1)
  3. 2表示:排名除以文档的长度
  4. 4表示:排名除以两个扩展词间的调和平均距离。只能使用ts_rank_cd实现
  5. 8表示:排名除以文档中单独词的数量
  6. 16表示:排名除以单独词数量的对数+1
  7. 32表示:排名除以排名本身+1

当指定多个标志位时,会按照所列的顺序依次进行转换。

需要特别注意的是,排序函数不使用任何全局信息,所以不可能产生一个某些情况下需要的1%或100%的理想标准值。标准化选项32 (rank/(rank+1))可用于所有规模的从零到一之间的排序,当然,这只是一个表面变化;它不会影响搜索结果的排序。

下面是一个例子,仅选择排名前三的匹配:

gbase=# SELECT id, title, ts_rank_cd(to_tsvector(body), query) AS rank

FROM pgweb, to_tsquery('america') query

WHERE query @@ to_tsvector(body)

ORDER BY rank DESC

LIMIT 3;

id |  title  | rank

----+---------+------

11 | Brazil  |  0.2

13 | Mexico  |  0.1

2 | America |  0.1

(3 rows)

这是使用标准化排序的相同例子:

gbase=# SELECT id, title, ts_rank_cd(to_tsvector(body), query, 32 /* rank/(rank+1) */ ) AS rank

FROM pgweb, to_tsquery('america') query

WHERE query @@ to_tsvector(body)

ORDER BY rank DESC

LIMIT 3;

id |  title  |   rank

----+---------+-----------

11 | Brazil  |  0.166667

13 | Mexico  | 0.0909091

2 | America | 0.0909091

(3 rows)

排序要遍历每个匹配的tsvector,因此资源消耗多,可能会因为I/O限制导致排序慢。可是这是很难避免的,因为实际查询中通常会有大量的匹配。

  1. 高亮结果

搜索结果的理想显示是:列出每篇文档中与搜索相关的部分,并标识为什么与查询相关。搜索引擎能够显示标识了搜索词的文档片段。GBase 8c提供了函数ts_headline支持这部分功能。

ts_headline([ config regconfig, ] document text, query tsquery [, options text ]) returns text

ts_headline的输入是带有查询条件的文档,其返回文档中的摘录,在摘录中查询词是高亮显示的。用来解析文档的分词器由config参数指定。如果省略config,则使用default_text_search_config的值所指定的分词器。

指定options字符串时,需由一个或多个option=value对组成,且必须用逗号分隔。options可以是下面的选项:

  1. StartSel,StopSel:分隔文档中出现的查询词,以区别于其他摘录词。当包含有空格或逗号时,必须用双引号将字符串引起来。
  2. MaxWords,MinWords:定义摘录的最长和最短值。
  3. ShortWord:在摘录的开始和结束会丢弃此长度或更短的词。默认值3会消除常见的英语冠词。
  4. HighlightAll:布尔标志。如果为真,整个文档将作为摘录。忽略前面三个参数的值。
  5. MaxFragments:要显示的文本摘录或片段的最大数量。默认值0表示选择非片段的摘录生成方法。 大于0的值表示选择基于片段的摘录生成。此方法查找带有尽可能多查询词的文本片段,并显示查询词周围的上下文片段。因此,查询词临近每个片段的中间,且查询词两边都有词。每个片段至多有MaxWords,并且长度为ShortWord或更短的词在每一个片段开始和结束被丢弃。如果在文档中没有找到所有的查询词,则文档中开头将显示MinWords单片段。
  6. FragmentDelimiter:当有一个以上的片段时,通过该字符串分隔这些片段。

不声明选项时,采用下面的缺省值:

StartSel=<b>, StopSel=</b>,

MaxWords=35, MinWords=15, ShortWord=3, HighlightAll=FALSE,

MaxFragments=0, FragmentDelimiter=" ... "

例如:

gbase=# SELECT ts_headline('english', 'The most common type of search is to find all documents containing given query terms and return them in order of their similarity to the query.', to_tsquery('query & similarity'));

ts_headline

-------------------------------------------------------

The most common type of search                       +

is to find all documents containing given query terms

(1 row)

  1. 附加功能

本节描述文本检索中一些额外的函数和操作符。

  1. 处理文档

GBase 8c提供了用来操作tsvector类型的函数和操作符。

  1. tsvector || tsvector

tsvector连接操作符返回一个新的tsvector类型,它综合了两个tsvector中词素和位置信息,并保留词素的位置信息和权重标签。右侧的tsvector的起始位置位于左侧tsvector的最后位置,因此,新生成的tsvector几乎等同于将两个原始文档字串连接后进行to_tsvector操作。(这个等价是不准确的,因为任何从左边tsvector中删除的停用词都不会影响结果,但是,在使用文本连接时,则会影响词素在右侧tsvector中的位置。)

相较于对文本进行连接后再执行to_tsvector操作,使用tsvector类型进行连接操作的优势在于,可以对文档的不同部分使用不同配置进行解析。因为setweight函数会对给定的tsvector中的语素进行统一设置,如果想要对文档的不同部分设置不同的权重,需要在连接之前对文本进行解析和权重设置,

  1. setweight(vector tsvector, weight "char") returns tsvector

setweight返回一个输入tsvector的副本,其中每一个位置都使用给定的权重做了标记。权值可以为A、B、C或D(D是tsvector副本的默认权重,并且不在输出中呈现)。当对tsvector进行连接操作时,这些权重标签将会被保留,文档不同部分以不同的权重进行排序。

注意:权重标签作用于位置,而不是词位。如果传入的tsvector已经被剥离了位置信息,那么setweight函数将什么都不做。

  1. length(vector tsvector) returns integer

返回vector中的词素的数量。

  1. strip(vector tsvector) returns tsvector

返回一个tsvector类型,其中包含输入的tsvector的同义词,但不包含任何位置和权重信息。虽然在相关性排序中,这里返回的tsvector要比未拆分的tsvector的作用小很多,但它通常都比未拆分的tsvector小的多。

  1. 处理查询

GBase 8c提供了函数和操作符用来操作tsquery类型的查询。

  1. tsquery && tsquery

返回两个给定查询tsquery的与结果。

  1. tsquery || tsquery

返回两个给定查询tsquery的或结果。

  1. !! tsquery

返回给定查询tsquery的非结果。

  1. tsquery <-> tsquery

返回给定查询tsquery的<->结果。例如:

gbase=# SELECT to_tsquery('fat') <-> to_tsquery('cat | rat');

?column?

-----------------------------

'fat' <-> ( 'cat' | 'rat' )

(1 row)

  1. tsquery_phrase(query1 tsquery, query2 tsquery [, distance integer ]) returns tsquery

返回两个给定查询tsquery的距离为distance个词位的匹配。例如:

gbase=# SELECT tsquery_phrase(to_tsquery('fat'), to_tsquery('cat'), 10);

tsquery_phrase

------------------

'fat' <10> 'cat'

(1 row)

  1. numnode(query tsquery) returns integer

返回tsquery中的节点数目(词素加操作符),这个函数在检查查询是否有效(返回值大于0),或者只包含停用词(返回值等于0)时,是有用的。例如:

gbase=# SELECT numnode('foo & bar'::tsquery);

numnode

---------

3

(1 row)

  1. querytree(query tsquery) returns text

返回可用于索引搜索的tsquery部分,该函数对于检测非索引查询是有用的(例如只包含停用词或否定项)。例如:

gbase=# SELECT querytree(to_tsquery('!defined'));

querytree

-----------

T

(1 row)

  1. 查询重写

ts_rewrite函数族可以从tsquery中搜索一个特定的目标子查询,并在该子查询每次出现的地方都替换为另一个子查询。 实际上这只是通过字串替换而得到的一个特定tsquery版本。目标子查询和替换查询组合起来可以被认为是一个重写规则。一组类似的重写规则可以为搜索提供强大的帮助。例如,可以使用同义词扩大搜索范围(例如,new york, big apple, nyc, gotham)或限制搜索范围在用户直接感兴趣的热点话题上。

  1. ts_rewrite (query tsquery, target tsquery, substitute tsquery) returns tsquery

ts_rewrite的这种形式只适用于一个单一的重写规则:任何出现目标子查询的地方都被无条件替换。例如:

gbase=# SELECT ts_rewrite('a & b'::tsquery, 'a'::tsquery, 'c'::tsquery);

ts_rewrite

------------

'b' & 'c'

(1 row)

  1. ts_rewrite (query tsquery, select text) returns tsquery

ts_rewrite的这种形式接受一个起始查询和SQL查询命令。 这里的查询命令是文本字串形式,必须产生两个tsquery列。查询结果的每一行,第一个字段的值(目标子查询) 都会被第二个字段(替代子查询)替换。

注意:当多个规则需要重写时,重写顺序非常重要; 因此在实践中需要使用ORDER BY将源查询按照某些字段进行排序。

例如:

gbase=# CREATE TABLE aliases (t tsquery PRIMARY KEY, s tsquery);

CREATE TABLE

gbase=# INSERT INTO aliases VALUES('a', 'c');

INSERT 0 1

gbase=# SELECT ts_rewrite('a & b'::tsquery, 'SELECT t,s FROM aliases');

ts_rewrite

------------

'b' & 'c'

(1 row)

可以通过更新表修改重写规则:

gbase=# UPDATE aliases SET s = to_tsquery('supernovae|sn & !nebulae') WHERE t = to_tsquery('supernovae');

UPDATE 0

gbase=# SELECT ts_rewrite(to_tsquery('supernovae & crab'), 'SELECT * FROM aliases');

ts_rewrite

-----------------------

'crab' & 'supernovae'

(1 row)

需要重写的规则越多,重写操作就越慢。因为它要检查每一个可能匹配的规则。为了过滤明显的非候选规则,可以使用tsquery类型的操作符来实现。在下面的例子中, 我们只选择那些可能与原始查询匹配的规则:

gbase=# SELECT ts_rewrite('a & b'::tsquery,'SELECT t,s FROM aliases WHERE ''a & b''::tsquery @> t');

ts_rewrite

------------

'b' & 'c'

(1 row)

  1. 收集文档统计数据

函数ts_stat可用于检查配置和查找候选停用词。

ts_stat(sqlquery text, [ weights text, ]

OUT word text, OUT ndoc integer,

OUT nentry integer) returns setof record

sqlquery是一个包含SQL查询语句的文本,该SQL查询将返回一个tsvector。ts_stat执行SQL查询语句并返回一个包含tsvector中每一个不同的语素(词)的统计信息。返回信息包括:

  1. word text:词位的值;
  2. ndoc integer:词出现过的文档(tsvector)的编号;
  3. nentry integer:词出现的总次数;

如果设置了权重条件,只有标记了对应权重的词素才会统计频率。

  1. 解析器

文本搜索解析器负责将原文档文本分解为多个记号,并标识每个记号的类型。这里的类型集由解析器本身定义。注意,解析器并不修改文本,它只是确定合理的单词边界。由于这一限制,人们更需要定制词典,而不是为每个应用程序定制解析器。当前GBase 8c提供了一种内置解析器pg_catalog.default,能识别23中记号类型,如下表所示:

别名

描述

例子

asciiword

单词,所有 ASCII 字母

elephant

word

单词,所有字母

mañana

numword

单词,字母和数字

beta1

asciihword

带连字符的单词,所有 ASCII

up-to-date

hword

带连字符的单词,所有字母

lógico-matemática

numhword

带连字符的单词,字母和数字

postgresql-beta1

hword_asciipart

带连字符的单词部分,所有 ASCII

postgresql in the context postgresql-beta1

hword_part

带连字符的单词部分,所有字母

lógico or matemática in the context lógico-matemática

hword_numpart

带连字符的单词部分,字母和数字

beta1 in the context postgresql-beta1

email

Email 地址

foo@example.com

protocol

协议头部

http://

url

URL

example.com/stuff/index.html

host

主机

example.com

url_path

URL 路径

/stuff/index.html, in the context of a URL

file

文件或路径名

/usr/local/foo.txt, if not within a URL

sfloat

科学记数法

-1.234e56

float

十进制记数法

-1.234

int

有符号整数

-1234

uint

无符号整数

1234

version

版本号

8.3.0

tag

XML 标签

<a href="dictionaries.html">

entity

XML 实体

&amp;

blank

空格符号

(其他不识别的任意空白或标点符号)

注意:对于解析器来说,一个“字母”的概念是由数据库的语言区域设置,即lc_ctype设置决定的。只包含基本ASCII字母的词被报告为一个单独的token类型,因为这类词有时需要被区分出来。大多数欧洲语言中,对token类型word和asciiword的处理方法是类似的。

email不支持某些由RFC 5322定义的有效电子邮件字符。具体来说,可用于email用户名的非字母数字字符仅包含句号、破折号和下划线。

解析器可能对同一内容进行重叠记号。例如,包含连字符的单词将作为一个整体进行报告,其组件也会分别被报告:

gbase=# SELECT alias, description, token FROM ts_debug('foo-bar-beta1');

alias      |               description                |     token

-----------------+------------------------------------------+---------------

numhword        | Hyphenated word, letters and digits      | foo-bar-beta1

hword_asciipart | Hyphenated word part, all ASCII          | foo

blank           | Space symbols                            | -

hword_asciipart | Hyphenated word part, all ASCII          | bar

blank           | Space symbols                            | -

hword_numpart   | Hyphenated word part, letters and digits | beta1

(6 rows)

这种行为是有必要的,因为它支持搜索整个复合词和各组件。这里是另一个例子:

gbase=# SELECT alias, description, token FROM ts_debug('http://example.com/stuff/index.html');

alias   |  description  |            token

----------+---------------+------------------------------

protocol | Protocol head | http://

url      | URL           | example.com/stuff/index.html

host     | Host          | example.com

url_path | URL path      | /stuff/index.html

(4 rows)

  1. 词典

词典用于定义停用词(stop words),即全文检索时不搜索哪些词。

词典还可以用于对同一词的不同形式进行规范化,这样同一个词的不同派生形式都可以进行匹配。规范化后的词称为词位(lexeme)。

除了提高检索质量外,词的规范化和删除停用词可以减少文档tsvector格式的大小,从而提高性能。词的规范化和删除停用词并不总是具有语言学意义,用户可以根据应用环境在词典定义文件中自定义规范化和删除规则。

一个词典是一个程序,接收标记作为输入,并返回:

  1. 如果标记在词典中已知,返回对应lexeme数组(注意,一个标记可能对应多个lexeme)。
  2. 一个lexeme。一个新标记会代替输入标记被传递给后继词典(当前词典可被称为过滤词典)。
  3. 如果标记在词典中已知,但它是一个停用词,返回空数组。
  4. 如果词典不能识别输入的标记,返回NULL。

GBase 8c提供了多种语言的预定义字典,并提供多种预定义的词典模板,同时可以根据用户需求创建新模板。

可以在文本搜索配置中定义一个解析器,以及一组用于处理该解析器的输出标记词典。对于解析器返回的每个标记类型,可以在配置中指定不同的词典列表进行处理。当解析器输出一种类型的标记后,在对应列表的每个字典中会查阅该标记,直到某个词典识别它。如果它被识别为一个停用词, 或者没有任何词典识别,该标记将被丢弃,即不被索引或检索到。通常情况下,第一个返回非空结果的词典决定了最终结果,后继词典将不会继续处理。但是一个过滤类型的词典可以依据规则替换输入标记,然后将替换后的标记传递给后继词典进行处理。

配置字典列表的一般规则是,第一个位置放置一个应用范围最小的、最具体化定义的词典,其次是更一般化定义的词典, 最后是一个普适定义的词典,比如Snowball词干词典或Simple词典。在下面例子中,对于一个针对天文学的文本搜索配置astro_en,可以定义标记类型asciiword(ASCII词)对应的词典列表为:天文术语的Synonym同义词词典,Ispell英语词典和Snowball英语词干词典。

ALTER TEXT SEARCH CONFIGURATION astro_en

ADD MAPPING FOR asciiword WITH astrosyn, english_ispell, english_stem;

过滤类型的词典可以放置在词典列表中除去末尾的任何地方,放置在末尾时是无效的。使用这些词典对标记进行部分规范化,可以有效简化后继词典的处理。

  1. 停用词

停用词是很常见的词,几乎出现在每一个文档中,并且没有区分值。因此,在全文搜索的语境下可忽视它们。例如,每一段英文文本都包含a和the,因此将其存储在索引中是没有用的。然而,停用词影响tsvector中的位置,同时位置也会影响相关度:

gbase=# SELECT to_tsvector('english','in the list of stop words');

to_tsvector

----------------------------

'list':3 'stop':5 'word':6

(1 row)

位置1、2、4是停用词,所以不显示。为包含和不包含停用词的文档计算出的排序是完全不同的:

gbase=# SELECT ts_rank_cd (to_tsvector('english','in the list of stop words'), to_tsquery('list & stop'));

ts_rank_cd

------------

0.05

(1 row)

gbase=# SELECT ts_rank_cd (to_tsvector('english','list stop words'), to_tsquery('list & stop'));

ts_rank_cd

------------

0.1

(1 row)

  1. 简单词典

简单(simple)词典首先将输入标记转换为小写字母,然后检查停用词表。如果识别为停用词则返回空数组,即表示该标记会被丢弃。否则,输入标记的小写形式作为规范化后的lexeme返回。此外,简单词典可通过设置参数Accept为false(默认值true),将非停用词报告为未识别,传递给后继词典继续处理。

例如:

首先创建simple模板的词典:

gbase=# CREATE TEXT SEARCH DICTIONARY public.simple_dict ( TEMPLATE = pg_catalog.simple, STOPWORDS = English );

CREATE TEXT SEARCH DICTIONARY

其中停用词文件全名为english.stop。

测试词典:

gbase=# SELECT ts_lexize('public.simple_dict','YeS');

ts_lexize

-----------

{yes}

(1 row)

gbase=# SELECT ts_lexize('public.simple_dict','The');

ts_lexize

-----------

{}

(1 row)

设置参数ACCEPT=false,使Simple词典返回NULL,而不是返回非停用词的小写形式:

gbase=# ALTER TEXT SEARCH DICTIONARY public.simple_dict ( Accept = false );

ALTER TEXT SEARCH DICTIONARY

gbase=# SELECT ts_lexize('public.simple_dict','YeS');

ts_lexize

-----------

(1 row)

gbase=# SELECT ts_lexize('public.simple_dict','The');

ts_lexize

-----------

{}

(1 row)

  1. 同义词词典

同义词(Synonym)词典用于定义、识别文档的同义词并转化,不支持词组。

Synonym词典可用于解决语言学相关问题,例如,为避免使单词"Paris"变成"pari",可在Synonym词典文件中定义一行"Paris paris",并将该词典放置在预定义的english_stem词典之前。

SELECT * FROM ts_debug('english', 'Paris');

alias   |   description   | token |  dictionaries  |  dictionary  | lexemes

-----------+-----------------+-------+----------------+--------------+---------

asciiword | Word, all ASCII | Paris | {english_stem} | english_stem | {pari}

CREATE TEXT SEARCH DICTIONARY my_synonym (

    TEMPLATE = synonym,

    SYNONYMS = my_synonyms

);

ALTER TEXT SEARCH CONFIGURATION english

    ALTER MAPPING FOR asciiword

    WITH my_synonym, english_stem;

SELECT * FROM ts_debug('english', 'Paris');

alias   |   description   | token |       dictionaries        | dictionary | lexemes

-----------+-----------------+-------+---------------------------+------------+---------

asciiword | Word, all ASCII | Paris | {my_synonym,english_stem} | my_synonym | {paris}

其中,同义词词典文件全名为my_synonyms.syn,路径为$SHAREDIR/tsearch_data/my_synonyms.syn。

星号(*)可用于词典文件中的同义词结尾,表示该同义词是一个前缀。在to_tsvector()中该星号将被忽略,但在to_tsquery()中会匹配该前缀并对应输出结果。

假设词典文件synonym_sample.syn内容如下:

postgres        pgsql

postgresql      pgsql

postgre pgsql

gogle   googl

indices index*

创建并使用词典:

gbase=# CREATE TEXT SEARCH DICTIONARY syn (template=synonym, synonyms='synonym_sample');

gbase=# SELECT ts_lexize('syn','indices');

ts_lexize

-----------

{index}

(1 row)

gbase=# CREATE TEXT SEARCH CONFIGURATION tst (copy=simple);

gbase=# ALTER TEXT SEARCH CONFIGURATION tst ALTER MAPPING FOR asciiword WITH syn;

gbase=# SELECT to_tsvector('tst','indices');

to_tsvector

-------------

'index':1

(1 row)

gbase=# SELECT to_tsquery('tst','indices');

to_tsquery

------------

'index':*

(1 row)

gbase=# SELECT 'indexes are very useful'::tsvector;

tsvector

---------------------------------

'are' 'indexes' 'useful' 'very'

(1 row)

gbase=# SELECT 'indexes are very useful'::tsvector @@ to_tsquery('tst','indices');

?column?

----------

t

(1 row)

  1. 分类词典

分类(Thesaurus)词典(缩写为TZ),是一组定义了词以及词组间关系的集合,包括广义词(BT)、狭义词(NT)、首选词、非首选词、相关词等。根据词典文件中的定义,TZ词典用一个指定的短语替换对应匹配的所有短语,并且可选择保留原始短语进行索引。TZ词典实际上是Synonym词典的一个扩展,增加了短语支持。分类词典的配置文件格式要求如下:

# this is a comment

sample word(s) : indexed word(s)

more sample word(s) : more indexed word(s)

...

由于TZ词典需要识别短语,所以在处理过程中必须保存当前状态并与解析器进行交互,以决定是否处理下一个词或是结束当前识别。此外,TZ词典配置时需谨慎,如果设置TZ词典仅处理asciiword类型的词,则类似one 7的分类词典定义将不会生效,因为uint类型的词不会传给TZ词典处理。

注意:在索引期间要用到分类词典,因此分类词典参数中的任何变化都要求重新索引。对于其他大多数类型的词典来说,类似添加或删除停用词这种修改并不需要强制重新索引。

例如:

使用thesaurus模板创建新的分类词典:

CREATE TEXT SEARCH DICTIONARY thesaurus_simple (

TEMPLATE = thesaurus,

DictFile = mythesaurus,

Dictionary = pg_catalog.english_stem

);

其中:

  1. thesaurus_simple是新词典的名称;
  2. mythesaurus是分类词典配置文件的基础名称(它的全名将是$SHAREDIR/tsearch_data/mythesaurus.ths,其中$SHAREDIR表示安装的共享数据目录);
  3. pg_catalog.english_stem是要用于分类词典正规化的子词典(这里是一个 Snowball 英语词干分析器)。注意子词典将拥有它自己的配置(例如停用词),但这里没有展示

可以在配置中把分类词典thesaurus_simple绑定到想要的记号类型上,例如:

ALTER TEXT SEARCH CONFIGURATION russian

ALTER MAPPING FOR asciiword, asciihword, hword_asciipart

WITH thesaurus_simple;

以创建名为thesaurus_astro的TZ词典为例:

创建一个简单的天文学词典thesaurus_astro,其中定义了两组天文短语及其同义词如下:

CREATE TEXT SEARCH DICTIONARY thesaurus_astro (

TEMPLATE = thesaurus,

DictFile = thesaurus_astro,

Dictionary = english_stem

);

创建词典后,将其绑定到对应文本搜索配置中需要处理的词类型上:

ALTER TEXT SEARCH CONFIGURATION russian

ALTER MAPPING FOR asciiword, asciihword, hword_asciipart

WITH thesaurus_astro, english_stem;

使用TZ词典:ts_lexize函数对于测试TZ词典作用不大,因为该函数是按照单个token处理输入。可以使用plainto_tsquery、to_tsvector、to_tsquery函数测试TZ词典,这些函数能够将输入分解成多个token(to_tsquery函数需要将输入加上引号)。

SELECT plainto_tsquery('supernova star');

plainto_tsquery

-----------------

'sn'

SELECT to_tsvector('supernova star');

to_tsvector

-------------

'sn':1

SELECT to_tsquery('''supernova star''');

to_tsquery

------------

'sn'

其中,supernova star匹配了词典thesaurus_astro定义中的supernovae stars,这是因为在thesaurus_astro词典定义中指定了Snowball类型的子词典english_stem,该词典移除了e和s。

如果同时需要索引原始短语,只要将其同时放置在词典定义文件中对应定义的右侧即可,如下:

supernovae stars : sn supernovae stars

SELECT plainto_tsquery('supernova star');

plainto_tsquery

-----------------------------

'sn' & 'supernova' & 'star'

  1. Ispell 词典

Ispell词典模板支持词法词典,它可以把一个词的各种语言学形式规范化成相同的词位。比如,一个Ispell英语词典可以匹配搜索词bank的词尾变化和词形变化,如banking、banked、banks、banks'和bank's等。

GBase 8c不提供任何预定义的Ispell类型词典或词典文件。dict文件和affix文件支持多种开源词典格式,包括Ispell、MySpell和Hunspell等。

首先,获取词典定义文件和词缀文件。

用户可以使用开源词典,直接获取的开源词典后缀名可能为.aff和.dic,此时需要将扩展名改为.affix和.dict。此外,对于某些词典文件,还需要使用下面的命令把字符转换成 UTF-8 编码,比如挪威语词典:

iconv -f ISO_8859-1 -t UTF-8 -o nn_no.affix nn_NO.aff

iconv -f ISO_8859-1 -t UTF-8 -o nn_no.dict nn_NO.dic

拷贝文件到$SHAREDIR/tsearch_data目录。

创建Ispell词典:

CREATE TEXT SEARCH DICTIONARY english_hunspell (

TEMPLATE = ispell,

DictFile = en_us,

AffFile = en_us,

Stopwords = English

);

这里,DictFile、AffFile和StopWords指定词典、词缀和停用词文件的基础名称。停用词文件的格式和前面解释的simple词典类型相同。

使用Ispell词典进行复合词拆分:

SELECT ts_lexize('norwegian_ispell', 'overbuljongterningpakkmesterassistent');

{over,buljong,terning,pakk,mester,assistent}

SELECT ts_lexize('norwegian_ispell', 'sjokoladefabrikk');

{sjokoladefabrikk,sjokolade,fabrikk}

MySpell不支持复合词,Hunspell对复合词有较好的支持。GaussDB 200仅支持Hunspell中基本的复合词操作。通常情况下,Ispell词典能够识别的词是一个有限集合,其后应该配置一个更广义的词典,例如一个可以识别所有词的Snowball词典。

  1. Snowball 词典

Snowball现在对许多语言提供词干分析算法。每一个算法懂得按照其语言中的拼写,如何缩减词的常见变体形式为一个基础或词干。一个Snowball词典要求一个language参数来标识要用哪种词干分析器,并且可以选择地指定一个停用词文件名来给出一个要被消除的词列表。

例如:

CREATE TEXT SEARCH DICTIONARY english_stem (

TEMPLATE = snowball,

Language = english,

StopWords = english

);

GBase 8c中预定义有一些可用的文本搜索配置,用户也可创建自定义的文本搜索配置。

  1. 配置示例

文本搜索配置(Text Search Configuration),指定了将文档转换成tsvector过程中所必需的组件:用于把文本分解成记号的解析器,以及用于将每一个记号转换成词位的词典。

每次to_tsvector或to_tsquery函数调用时,都需要指定一个文本搜索配置来指定具体的处理过程。配置参数default_text_search_config指定了默认的文本搜索配置,当文本搜索函数中没有显式指定文本搜索配置参数时,将会使用该默认值进行处理。

GBase 8c中预定义有一些可用的文本搜索配置,用户也可创建自定义的文本搜索配置。此外,为了便于管理文本搜索对象,还提供有多个gsql元命令,可以显示有关文本搜索对象的信息。

例如:

创建配置pg,从复制内建的english配置:

CREATE TEXT SEARCH CONFIGURATION public.pg ( COPY = pg_catalog.english );

创建同义词词典定义文件pg_dict.syn,内容如下:

postgres    pg

pgsql       pg

postgresql  pg

创建同义词词典:

CREATE TEXT SEARCH DICTIONARY pg_dict (

TEMPLATE = synonym,

SYNONYMS = pg_dict

);

创建一个Ispell词典english_ispell(词典定义来源开源词典):

CREATE TEXT SEARCH DICTIONARY english_ispell (

TEMPLATE = ispell,

DictFile = english,

AffFile = english,

StopWords = english

);

设置文本搜索配置pg:

ALTER TEXT SEARCH CONFIGURATION pg

ALTER MAPPING FOR asciiword, asciihword, hword_asciipart,

word, hword, hword_part

WITH pg_dict, english_ispell, english_stem;

在文本搜索配置中,选择设置不索引或搜索某些记号类型:

ALTER TEXT SEARCH CONFIGURATION pg

DROP MAPPING FOR email, url, url_path, sfloat, float;

对创建的配置进行测试:

SELECT * FROM ts_debug('public.pg', '

PostgreSQL, the highly scalable, SQL compliant, open source object-relational

database management system, is now undergoing beta testing of the next

version of our software.

');

设置会话使用新配置:

\dF

List of text search configurations

Schema  | Name | Description

---------+------+-------------

public  | pg   |

SET default_text_search_config = 'public.pg';

SET

SHOW default_text_search_config;

default_text_search_config

----------------------------

public.pg

  1. 测试和调试文本搜索

    1. 配置测试

函数ts_debug允许简单地测试一个文本搜索配置。

ts_debug([ config regconfig, ] document text,

OUT alias text,

OUT description text,

OUT token text,

OUT dictionaries regdictionary[],

OUT dictionary regdictionary,

OUT lexemes text[])

returns setof record

ts_debug显示document的每个记号信息,记号是由解析器生成,由指定的词典进行处理。如果忽略对应参数,则使用config指定的分词器或者default_text_search_config指定的分词器。

ts_debug为解析器在文本中标识的每一个记号返回一行。被返回的列是:

  1. alias text:记号类型的短名称;
  2. description text:记号类型的描述;
  3. token text:记号的文本;
  4. dictionaries regdictionary[]:配置为这种记号类型选择的词典;
  5. dictionary regdictionary:识别该记号的词典,如果没有词典能识别则为NULL;
  6. lexemes text[]:识别该记号的词典产生的词位,如果没有词典能识别则为NULL;一个空数组({})表示该记号被识别为一个停用词。

一个简单的例子:

SELECT * FROM ts_debug('english','a fat  cat sat on a mat - it ate a fat rats');

alias   |   description   | token |  dictionaries  |  dictionary  | lexemes

-----------+-----------------+-------+----------------+--------------+---------

asciiword | Word, all ASCII | a     | {english_stem} | english_stem | {}

blank     | Space symbols   |       | {}             |              |

asciiword | Word, all ASCII | fat   | {english_stem} | english_stem | {fat}

blank     | Space symbols   |       | {}             |              |

asciiword | Word, all ASCII | cat   | {english_stem} | english_stem | {cat}

blank     | Space symbols   |       | {}             |              |

asciiword | Word, all ASCII | sat   | {english_stem} | english_stem | {sat}

blank     | Space symbols   |       | {}             |              |

asciiword | Word, all ASCII | on    | {english_stem} | english_stem | {}

blank     | Space symbols   |       | {}             |              |

asciiword | Word, all ASCII | a     | {english_stem} | english_stem | {}

blank     | Space symbols   |       | {}             |              |

asciiword | Word, all ASCII | mat   | {english_stem} | english_stem | {mat}

blank     | Space symbols   |       | {}             |              |

blank     | Space symbols   | -     | {}             |              |

asciiword | Word, all ASCII | it    | {english_stem} | english_stem | {}

blank     | Space symbols   |       | {}             |              |

asciiword | Word, all ASCII | ate   | {english_stem} | english_stem | {ate}

blank     | Space symbols   |       | {}             |              |

asciiword | Word, all ASCII | a     | {english_stem} | english_stem | {}

blank     | Space symbols   |       | {}             |              |

asciiword | Word, all ASCII | fat   | {english_stem} | english_stem | {fat}

blank     | Space symbols   |       | {}             |              |

asciiword | Word, all ASCII | rats  | {english_stem} | english_stem | {rat}

  1. 解析器测试

函数ts_parse可以直接测试文本搜索解析器:

ts_parse(parser_name text, document text,

OUT tokid integer, OUT token text) returns setof record

ts_parse(parser_oid oid, document text,

OUT tokid integer, OUT token text) returns setof record

ts_parse解析给定的document并返回一系列记录,每一个记录对应一个由解析产生的记号。每一个记录包括一个tokid展示分配给记号的类型以及一个token展示记号的文本。例如:

SELECT * FROM ts_parse('default', '123 - a number');

tokid | token

-------+--------

22 | 123

12 |

12 | -

1 | a

12 |

1 | number

ts_token_type(parser_name text, OUT tokid integer,

OUT alias text, OUT description text) returns setof record

ts_token_type(parser_oid oid, OUT tokid integer,

OUT alias text, OUT description text) returns setof record

ts_token_type返回一个表,该表描述指定解析器能够识别的每一种记号类型。对于每一种记号类型,该表给出了解析器用来标注该类型记号的整数tokid,还给出了在配置命令中命名该记号类型的alias,以及一个简短的description。例如:

SELECT * FROM ts_token_type('default');

tokid |      alias      |               description

-------+-----------------+------------------------------------------

1 | asciiword       | Word, all ASCII

2 | word            | Word, all letters

3 | numword         | Word, letters and digits

4 | email           | Email address

5 | url             | URL

6 | host            | Host

7 | sfloat          | Scientific notation

8 | version         | Version number

9 | hword_numpart   | Hyphenated word part, letters and digits

10 | hword_part      | Hyphenated word part, all letters

11 | hword_asciipart | Hyphenated word part, all ASCII

12 | blank           | Space symbols

13 | tag             | XML tag

14 | protocol        | Protocol head

15 | numhword        | Hyphenated word, letters and digits

16 | asciihword      | Hyphenated word, all ASCII

17 | hword           | Hyphenated word, all letters

18 | url_path        | URL path

19 | file            | File or path name

20 | float           | Decimal notation

21 | int             | Signed integer

22 | uint            | Unsigned integer

23 | entity          | XML entity

  1. 词典测试

函数ts_lexize用于进行词典测试。

ts_lexize(dict regdictionary, token text) returns text[]

如果输入的token可以被词典识别,那么ts_lexize返回词素的数组;如果token可以被词典识别但它是一个停用词,则返回空数组;如果是一个不可识别的词则返回NULL。

例如:

SELECT ts_lexize('english_stem', 'stars');

ts_lexize

-----------

{star}

SELECT ts_lexize('english_stem', 'a');

ts_lexize

-----------

{}

注意:ts_lexize函数支持单一token,不支持文本。

  1. 限制

GBase 8c的全文检索特性当前限制是:

  1. 每一个词位的长度必须小于 2K 字节;
  2. 一个tsvector(词位 + 位置)的长度必须小于 1 兆字节;
  3. 词位的数量必须小于 264;
  4. tsvector中的位置值必须大于 0 并且小于 16,383;
  5. <N>(FOLLOWED BY)tsquery操作符中的匹配距离不能超过 16,384;
  6. 每个词位不超过 256 个位置;
  7. 一个tsquery中结点(词位 + 操作符)的个数必须小于 32,768。

GBASE 8C——SQL参考 5 全文检索相关推荐

  1. GBASE 8C——SQL参考6 sql语法(12)

    EXECUTE 功能描述 执行一个前面准备好的预备语句.因为一个预备语句只在会话的生命期里存在,那么预备语句必须是在当前会话的前些时候用PREPARE语句创建的. 语法格式 EXECUTE name ...

  2. GBASE 8C——SQL参考 2 函数和操作符

    函数和操作符 GBase 8c提供了大量的函数和操作符,用户也可以自己定义函数和操作符. 逻辑操作符 常用的逻辑操作符: AND OR NOT 比较操作符 操作符 描述 < 小于 > 大于 ...

  3. GBASE 8C——SQL参考6 sql语法(1)

    SQL语法 ABORT 功能描述 回滚当前事务并且撤销所有当前事务中所做的更改. 作用等同于ROLLBACK,更推荐使用ROLLBACK. 语法格式 ABORT [ WORK | TRANSACTIO ...

  4. GBase 8s SQL 指南:教程———3编写SELECT语句

    3编写SELECT语句 SELECT语句是最重要且最复杂的SQL语句.可使用它和SQL语句INSERT. UPDATE和DELETE操纵数据.可以使用SELECT语句从数据库检索数据.将它用作 INS ...

  5. GBase 8c V3.0.0版本关键字介绍

    SQL里有保留字和非保留字之分.根据标准,保留字决不能用做其他标识符.非保留字只是在特定的环境里有特殊的含义,而在其他环境里是可以用做标识符的. 标识符的命名需要遵守如下规范: 标识符需要为字母.下划 ...

  6. GBase 8c 全文检索-表检索

    在没有索引的情况下,使用GBase 8c全文检索功能检索表,需要@@操作符.例如,查询文档中每行title匹配friend: gbase=# SELECT id, body, title FROM p ...

  7. 8c SQL手册 三

    枚举类型 枚举(enum)类型是一个静态.有序的集合构成的数据类型.可以使用CREATE TYPE命令创建,例如: CREATE TYPE mood AS ENUM ('sad', 'ok', 'ha ...

  8. GBase 8c 开发接口

    GBase 8c 接口驱动可以有效实现对上层应用请求的负载进行均衡,应用调用接口驱动配置多个集群节点的 IP,接口驱动的内部进行连接的负载均衡. GBase 8c ODBC GBase 8c ODBC ...

  9. GBase 8c开发接口

    GBase 8c接口驱动可以有效实现对上层应用请求的负载进行均衡,应用调用接口驱动配置多个集群节点的IP,接口驱动的内部进行连接的负载均衡. GBase 8c ODBC GBase 8c ODBC是G ...

最新文章

  1. 和老同事的谈话:关于职业生涯以及MDA
  2. 如何停止电脑正在运行的VBS程序?
  3. c++中的函数模版和类模版
  4. GPS及惯性传感器在无人驾驶中的应用
  5. 机器学习之手把手实现,第 2 部分 频繁项集与关联规则 FP-growth 的原理和实现...
  6. 不要轻易和少妇上床:金融危机是这…
  7. dede plus ad js.php,织梦程序中plus文件作用介绍及安全设置
  8. 菲波那契数列(信息学奥赛一本通-T1201)
  9. TStringList 的Sorted属性
  10. auto cad 打印颜色变浅_CAD制图软件中如何设置CAD打印样式表(CTB)?
  11. jmap查询JVM堆内存
  12. C++后台开发学习路线
  13. 计算机海报制作过程以及内容,《海报的设计与制作》计算机职教课件.ppt
  14. xlsx格式表格汉字批量转音节,不带声调(python)
  15. OPPO加入连接标准联盟董事会;BOSE为领克09汽车打造Centerpoint环绕声音响系统 | 全球TMT...
  16. Windows11专业版安装USBCAN-II驱动后报错“……无法加载这个硬件的设备驱动程序……(代码39)”解决方案
  17. 高德地图js-api简单使用
  18. java开发工作交接一般要多久_交接工作一般交接到什么程度?
  19. 树莓派玩黄油,编译运行ONScripter
  20. Chrome Console 小技巧之 01 如何启动XHR监控网络请求

热门文章

  1. 什么是工业4.0? 本文已经帮你解释清楚了
  2. 论文推荐:陈国生 实证化中医基础理论
  3. k8s中部署prometheus监控告警系统-prometheus系列文章第一篇
  4. wordpress 调整段落间距和字体大小
  5. keilC51编译常见错误和警告说明
  6. [Android自定义控件]双圆圈内外旋转菜单
  7. 十六进制账号登录QQ、TIM
  8. STM32F103学习之系统时钟配置
  9. 语义分割评估指标MIOU
  10. 数据结构PTA 基础实验7-2.1 魔法优惠券