VastbaseG100

基于openGauss内核开发的企业级关系型数据库。

Menu

词典

词典概述

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

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

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

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

  • 如果token在词典中已知,返回对应lexeme数组(注意,一个标记可能对应多个lexeme)。

  • 一个lexeme。一个新token会代替输入token被传递给后继词典(当前词典可被称为过滤词典)。

  • 如果token在词典中已知,但它是一个停用词,返回空数组。

  • 如果词典不能识别输入的token,返回NULL。

Vastbase提供了多种语言的预定义字典,同时提供了五种预定义的词典模板,分别是Simple,Synonym,Thesaurus,Ispell,和Snowball,可用于创建自定义参数的新词典。

在使用全文检索时,建议用户:

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

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

    vastbase=# ALTER TEXT SEARCH CONFIGURATION astro_en 
    ADD MAPPING FOR asciiword WITH astro_syn, english_ispell, english_stem;
    

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

停用词

停用词是很常见的词,几乎出现在每一个文档中,并且没有区分值。因此,在全文搜索的语境下可忽视它们。停用词处理逻辑和词典类型相关。例如,Ispell词典会先对标记进行规范化,然后再查看停用词表,而Snowball词典会最先检查输入标记是否为停用词。

例如,每个英文文本包含像a和the的单词,因此没必要将它们存储在索引中。然而,停用词影响tsvector中的位置,同时位置也会影响相关度:

vastbase=# SELECT to_tsvector('english','in the list of stop words'); 
        to_tsvector 
---------------------------- 
 'list':3 'stop':5 'word':6

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

vastbase=# SELECT ts_rank_cd (to_tsvector('english','in the list of stop words'), to_tsquery('list & stop')); 
 ts_rank_cd 
------------ 
        .05 
 
vastbase=# SELECT ts_rank_cd (to_tsvector('english','list stop words'), to_tsquery('list & stop')); 
 ts_rank_cd 
------------ 
         .1

Simple词典

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

注意事项

  • 大多数词典的功能依赖于词典定义文件,词典定义文件名仅支持小写字母、数字、下划线组合。

  • 临时模式pg_temp下不允许创建词典。

  • 词典定义文件的字符集编码必须为UTF-8格式。实际应用时,如果与数据库的字符编码格式不一致,在读入词典定义文件时会进行编码转换。

  • 通常情况下,每个session仅读取词典定义文件一次,当且仅当在第一次使用该词典时。需要修改词典文件时,可通过ALTER TEXT SEARCH DICTIONARY命令进行词典定义文件的更新和重新加载。

操作步骤

步骤1 创建Simple词典。

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

其中,停用词表文件全名为english.stop。关于创建simple词典的语法和更多参数,请参见12.19.53CREATE TEXT SEARCH DICTIONARY。

步骤2 使用Simple词典。

vastbase=# SELECT ts_lexize('public.simple_dict','YeS'); 
 ts_lexize  
----------- 
 {yes} 
(1 row) 
 
vastbase=# SELECT ts_lexize('public.simple_dict','The'); 
 ts_lexize  
----------- 
 {} 
(1 row)

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

vastbase=# ALTER TEXT SEARCH DICTIONARY public.simple_dict ( Accept = false ); 
ALTER TEXT SEARCH DICTIONARY 
vastbase=# SELECT ts_lexize('public.simple_dict','YeS'); 
 ts_lexize  
----------- 
 
(1 row) 
 
vastbase=# SELECT ts_lexize('public.simple_dict','The'); 
 ts_lexize  
----------- 
 {} 
(1 row)

Synonym词典

Synonym词典用于定义、识别token的同义词并转化,不支持词组(词组形式的同义词可用Thesaurus词典定义,详细请参见12.8.6.5Thesaurus词典)。

示例

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

    vastbase=# SELECT * FROM ts_debug('english', 'Paris'); 
    alias   |   description   | token |  dictionaries  |  dictionary  | lexemes  
    -----------+-----------------+-------+----------------+--------------+--------- 
    asciiword | Word, all ASCII | Paris | {english_stem} | english_stem | {pari} 
    (1 row) 
     
    vastbase=# CREATE TEXT SEARCH DICTIONARY my_synonym ( 
    TEMPLATE = synonym, 
    SYNONYMS = my_synonyms, 
    FILEPATH = 'file:///home/dicts/'  
    ); 
     
    vastbase=# ALTER TEXT SEARCH CONFIGURATION english 
    ALTER MAPPING FOR asciiword 
    WITH my_synonym, english_stem; 
     
    vastbase=# SELECT * FROM ts_debug('english', 'Paris'); 
    alias   |   description   | token |       dictionaries        | dictionary | lexemes  
    -----------+-----------------+-------+---------------------------+------------+--------- 
    asciiword | Word, all ASCII | Paris | {my_synonym,english_stem} | my_synonym | {paris} 
    (1 row) 
     
    vastbase=# SELECT * FROM ts_debug('english', 'paris'); 
    alias   |   description   | token |       dictionaries        | dictionary | lexemes  
    -----------+-----------------+-------+---------------------------+------------+--------- 
    asciiword | Word, all ASCII | Paris | {my_synonym,english_stem} | my_synonym | {paris} 
    (1 row) 
     
    vastbase=# ALTER TEXT SEARCH DICTIONARY my_synonym ( CASESENSITIVE=true); 
     
    vastbase=# SELECT * FROM ts_debug('english', 'Paris'); 
    alias   |   description   | token |       dictionaries        | dictionary | lexemes  
    -----------+-----------------+-------+---------------------------+------------+--------- 
    asciiword | Word, all ASCII | Paris | {my_synonym,english_stem} | my_synonym | {paris} 
    (1 row) 
     
    vastbase=# SELECT * FROM ts_debug('english', 'paris'); 
    alias   |   description   | token |       dictionaries        | dictionary | lexemes  
    -----------+-----------------+-------+---------------------------+------------+--------- 
    asciiword | Word, all ASCII | Paris | {my_synonym,english_stem} | my_synonym | {pari} 
    (1 row) 
    

    其中,同义词词典文件全名为my_synonyms.syn,所在目录为当前连接数据库主节点的/home/dicts/下。关于创建词典的语法和更多参数,请参见12.19.21ALTER TEXT SEARCH DICTIONARY。

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

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

    postgres        pgsql 
    postgresql      pgsql  
    postgre pgsql  
    gogle   googl  
    indices index*
    

    创建并使用词典:

    vastbase=# CREATE TEXT SEARCH DICTIONARY syn ( 
    TEMPLATE = synonym, 
    SYNONYMS = synonym_sample 
    ); 
     
    vastbase=# SELECT ts_lexize('syn','indices'); 
    ts_lexize  
    ----------- 
    {index} 
    (1 row) 
     
    vastbase=# CREATE TEXT SEARCH CONFIGURATION tst (copy=simple); 
     
    vastbase=# ALTER TEXT SEARCH CONFIGURATION tst ALTER MAPPING FOR asciiword WITH syn; 
     
    vastbase=# SELECT to_tsvector('tst','indices'); 
    to_tsvector  
    ------------- 
    'index':1 
    (1 row) 
     
    vastbase=# SELECT to_tsquery('tst','indices'); 
    to_tsquery  
    ------------ 
    'index':* 
    (1 row) 
     
    vastbase=# SELECT 'indexes are very useful'::tsvector; 
            tsvector              
    --------------------------------- 
    'are' 'indexes' 'useful' 'very' 
    (1 row) 
     
    vastbase=# SELECT 'indexes are very useful'::tsvector @@ to_tsquery('tst','indices'); 
    ?column?  
    ---------- 
    t 
    (1 row)
    

Thesaurus词典

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

注意事项

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

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

操作步骤

步骤1 创建一个名为thesaurus_astro的TZ词典。

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

supernovae stars : sn  
crab nebulae : crab

执行如下语句创建TZ词典:

vastbase=# CREATE TEXT SEARCH DICTIONARY thesaurus_astro ( 
    TEMPLATE = thesaurus, 
    DictFile = thesaurus_astro, 
    Dictionary = pg_catalog.english_stem, 
    FILEPATH = 'file:///home/dicts/' 
);

其中,词典定义文件全名为thesaurus_astro.ths,所在目录为当前连接数据库主节点的/home/dicts/下。子词典pg_catalog.english_stem是预定义的Snowball类型的英语词干词典,用于规范化输入词,子词典自身相关配置(例如停用词等)不在此处显示。关于创建词典的语法和更多参数,请参见12.19.53CREATE TEXT SEARCH DICTIONARY。

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

vastbase=# ALTER TEXT SEARCH CONFIGURATION russian 
    ALTER MAPPING FOR asciiword, asciihword, hword_asciipart 
    WITH thesaurus_astro, english_stem;

步骤3 使用TZ词典。

  • 测试TZ词典。

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

    vastbase=# SELECT plainto_tsquery('russian','supernova star'); 
    plainto_tsquery  
    ----------------- 
    'sn' 
    (1 row) 
     
    vastbase=# SELECT to_tsvector('russian','supernova star'); 
    to_tsvector  
    ------------- 
    'sn':1 
    (1 row) 
     
    vastbase=# SELECT to_tsquery('russian','''supernova star'''); 
    to_tsquery  
    ------------ 
    'sn' 
    (1 row) 
    

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

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

    supernovae stars : sn supernovae stars 
     
    vastbase=# ALTER TEXT SEARCH DICTIONARY thesaurus_astro ( 
    DictFile = thesaurus_astro, 
    FILEPATH = 'file:///home/dicts/'); 
     
    vastbase=# SELECT plainto_tsquery('russian','supernova star'); 
       plainto_tsquery        
    ----------------------------- 
    'sn' & 'supernova' & 'star' 
    (1 row)
    

Ispell词典

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

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

操作步骤

步骤1 获取词典定义文件和词缀文件。

用户可以使用开源词典,直接获取的开源词典后缀名可能为.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

步骤2 创建Ispell词典。

vastbase=# CREATE TEXT SEARCH DICTIONARY norwegian_ispell ( 
    TEMPLATE = ispell, 
    DictFile = nn_no, 
    AffFile = nn_no, 
    FilePath = 'file:///home/dicts' 
);

其中,词典文件全名为nn_no.dict和nn_no.affix,所在目录为当前连接数据库主节点的/home/dicts/下。关于创建词典的语法和更多参数,请参见12.19.53CREATE TEXT SEARCH DICTIONARY。

步骤3 使用Ispell词典进行复合词拆分。

vastbase=# SELECT ts_lexize('norwegian_ispell', 'sjokoladefabrikk'); 
      ts_lexize       
--------------------- 
 {sjokolade,fabrikk} 
(1 row) 

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

Snowball词典

Snowball词典模板支持词干分析词典,基于Martin Porter的Snowball项目,内置有许多语言的词干分析算法。Vastbase中预定义有多种语言的Snowball词典,可通过系统表15.2.63PG_TS_DICT查看预定义的词干分析词典以及支持的语言词干分析算法。

无论是否可以简化,Snowball词典将标示所有输入为已识别,因此它应当被放置在词典列表的最后。把Snowball词典放在任何其他词典前面会导致后继词典失效,因为输入token不会通过Snowball词典进入到下一个词典。

关于Snowball词典的语法,请参见12.19.53CREATE TEXT SEARCH DICTIONARY。