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值用连接操作符||合并起来。
2、解析查询
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)
这里,所有输入的标点都被作为空间符号并且丢弃。