词典
词典概述
词典用于定义停用词(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。