文本搜索词典

文本搜索词典

由Greenplum数据库全文搜索解析器生成的token通过一系列字典传递以产生标准化术语或“词位”。 不同种类的词典可用于以不同方式和不同语言过滤和转换token。

本节包含以下子主题:

关于文本搜索词典

字典用于消除在搜索中不应考虑的单词(停用单词),并对单词进行标准化,以使相同单词的不同派生形式匹配。 成功标准化的单词称为词位。 除了提高搜索质量之外,停止词的标准化和删除减少了文档的tsvector表示的大小,从而提高了性能。 规范化并不总是具有语言意义,通常依赖于应用语义。

标准化的一些例子:

  • 语法 - Ispell词典试图将输入词减少到标准化形式; 词干词典删除单词结尾
  • 可以规范化URL位置以使URL等效匹配:
    • http://www.pgsql.ru/db/mw/index.html
    • http://www.pgsql.ru/db/mw/
    • http://www.pgsql.ru/db/../db/mw/index.html
  • 颜色名称可以用它们的十六进制值替换,例如红色,绿色,蓝色,品红色 -> FF0000,00FF00,0000FF,FF00FF
  • 如果索引数字,我们可以删除一些小数位以减少可能数字的范围,因此例如3.14159265359,3.1415926,3.14在归一化后将是相同的,如果小数点后只保留两位数。

字典是一个接受token作为输入并返回的程序:A dictionary is a program that accepts a token as input and returns:

  • 如果字典已知输入token(注意一个token可以产生多个词位),则为词位数组
  • 设置了TSL_FILTER标志的单个词位,用新token替换原始token以传递给后续字典(执行此操作的字典称为过滤字典)
  • 如果字典知道token,则为空数组,但它是停止词
  • 如果字典无法识别输入token,则为NULL

Greenplum数据库为许多语言提供预定义的词典。 还有一些预定义模板可用于创建具有自定义参数的新词典。 每个预定义的字典模板如下所述。 如果没有适合的现有模板,则可以创建新模板; 有关示例,请参阅Greenplum数据库分发的contrib/区域。

文本搜索配置将解析器与一组字典绑定在一起,以处理解析器的输出token。 对于解析器可以返回的每个token类型,配置指定单独的字典列表。 当解析器找到该类型的token时,依次查询列表中的每个字典,直到某些字典将其识别为已知字。 如果它被识别为停止词,或者没有字典识别该token,则它将被丢弃并且不被索引或搜索。 通常,返回non-NULL输出的第一个字典确定结果,并且不查阅任何剩余的字典; 但是过滤字典可以用修改后的单词替换给定单词,然后将其传递给后续词典。

配置字典列表的一般规则是首先放置最窄,最具体的字典,然后是更一般的字典,最后是一个非常通用的字典,如Snowball stemmer或simple,它可以识别所有内容。 例如,对于特定于天文学的搜索(astro_en配置),可以将token类型asciiword(ASCII字)绑定到天文术语的同义词词典,通用英语词典和Snowball英语词干分析器:

ALTER TEXT SEARCH CONFIGURATION astro_en
    ADD MAPPING FOR asciiword WITH astrosyn, english_ispell, english_stem;

过滤字典可以放在列表中的任何位置,除非它没有用处。 过滤词典对于部分规范化单词以简化后续词典的任务非常有用。 例如,过滤字典可用于从重音字母中删除重音,如非重音模块所做的那样。

停止词

停止词是非常常见的词,几乎出现在每个文档中,并且没有区分值。 因此,在全文搜索的上下文中可以忽略它们。 例如,每个英文文本都包含像a和the这样的单词,因此将它们存储在索引中是没用的。 但是,停止词会影响tsvector中的位置,从而影响排名:

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

丢失的位置1,2,4是因为停止词。 计算带有和不带停止词的文档的等级是完全不同的:

SELECT ts_rank_cd (to_tsvector('english','in the list of stop words'), to_tsquery('list & stop'));
 ts_rank_cd
------------
       0.05

SELECT ts_rank_cd (to_tsvector('english','list stop words'), to_tsquery('list & stop'));
 ts_rank_cd
------------
        0.1

它取决于特定字典如何处理停止词。 例如,ispell词典首先将单词标准化,然后查看停止词列表,而Snowball词干表首先检查停止词列表。 不同行为的原因是试图降低噪音。

简单的字典

简单字典模板通过将输入token转换为小写字母并针对停用字文件进行检查来进行操作。 如果在文件中找到它,则返回一个空数组,导致该token被丢弃。 如果不是,则将该词的小写形式作为标准化词位返回。 或者,可以将字典配置为将非停止词报告为无法识别,允许将它们传递到列表中的下一个词典。

以下是使用简单模板的字典定义示例:

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

这里,english是停止词文件的基本名称。 该文件的全名为$SHAREDIR/tsearch_data/english.stop, 其中$SHAREDIR表示Greenplum数据库安装的共享数据目录, 通常为/usr/local/greenplum-db-<version>/share/postgresql (使用pg_config --sharedir来确定它,如果您不确定。 文件格式只是一个单词列表,每行一个。 空行和尾随空格被忽略,大写折叠为小写,但没有对文件内容进行其他处理。 often

现在我们可以测试我们的字典:

SELECT ts_lexize('public.simple_dict','YeS');
 ts_lexize
-----------
 {yes}

SELECT ts_lexize('public.simple_dict','The');
 ts_lexize
-----------
 {}

如果在停止词文件中找不到,我们也可以选择返回NULL而不是小写的词。 通过将字典的Accept参数设置为false来选择此行为。 继续这个例子:

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

SELECT ts_lexize('public.simple_dict','YeS');
 ts_lexize
-----------
 {yes}

SELECT ts_lexize('public.simple_dict','The');
 ts_lexize
-----------
 {}

使用Accept = true的默认设置,只在字典列表的末尾放置一个简单的字典是有用的,因为它永远不会将任何token传递给后面的字典。 相反,Accept = false仅在至少有一个后续字典时才有用。

CAUTION:
大多数类型的词典都依赖于配置文件,例如停止词的文件。 这些文件必须以UTF-8编码存储。 如果它们被读入服务器,它们将被转换为实际的数据库编码(如果不同)。
CAUTION:
通常,数据库会话将首次在会话中使用时读取字典配置文件一次。 如果修改配置文件并希望强制现有会话获取新内容,请在字典上发出ALTER TEXT SEARCH DICTIONARY命令。 这可以是“虚拟”更新,实际上不会更改任何参数值。

同义词词典

此词典模板用于创建用同义词替换单词的词典。 不支持短语 - 使用同义词库模板(同义词词典)。 同义词词典可用于克服语言问题,例如,防止英语词干分词将“Paris”一词减少为“pari”。 在同义词词典中有一个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}

同义词模板所需的唯一参数是SYNONYMS,它是其配置文件的基本名称 - 上例中的my_synonyms。 该文件的全名为$SHAREDIR/tsearch_data/my_synonyms.syn(其中$SHAREDIR表示Greenplum数据库安装的共享数据目录)。 文件格式只是每个要替换的单词一行,单词后跟其同义词,用空格分隔。 空行和尾随空格将被忽略。

同义词模板还有一个可选参数CaseSensitive,默认为false。 当CaseSensitivefalse时,同义词文件中的单词将折叠为小写,输入token也是如此。 如果是true,则单词和token不会折叠为小写,而是按原样进行比较。

星号(*)可以放在配置文件中同义词的末尾。 这表示同义词是前缀。 当在to_tsvector()中使用该条目时,将忽略星号,但在to_tsquery()中使用该条目时,结果将是具有前缀匹配标记的查询项(请参阅解析查询)。 例如,假设我们在$SHAREDIR/tsearch_data/synonym_sample.syn中有这些条目:

postgres pgsql postgresql pgsql postgre pgsql 
gogle googl 
indices index*

然后我们将得到这些结果:

mydb=# CREATE TEXT SEARCH DICTIONARY syn (template=synonym, synonyms='synonym_sample');
mydb=# SELECT ts_lexize('syn','indices');
 ts_lexize
-----------
 {index}
(1 row)

mydb=# CREATE TEXT SEARCH CONFIGURATION tst (copy=simple);
mydb=# ALTER TEXT SEARCH CONFIGURATION tst ALTER MAPPING FOR asciiword WITH syn;
mydb=# SELECT to_tsvector('tst','indices');
 to_tsvector
-------------
 'index':1
(1 row)

mydb=# SELECT to_tsquery('tst','indices');
 to_tsquery
------------
 'index':*
(1 row)

mydb=# SELECT 'indexes are very useful'::tsvector;
            tsvector             
---------------------------------
 'are' 'indexes' 'useful' 'very'
(1 row)

mydb=# SELECT 'indexes are very useful'::tsvector @@ to_tsquery('tst','indices');
 ?column?
----------
 t
(1 row)

同义词词典

同义词词典(有时缩写为TZ)是一组词,包括有关词和短语关系的信息,即更宽泛的术语(BT),更窄的术语(NT),首选术语,非首选术语,相关术语,等等。

基本上,同义词词典将所有非首选术语替换为一个优选术语,并且可选地,也保留用于索引的原始术语。 Greenplum数据库的同义词词典的当前实现是同义词词典的扩展,增加了词组支持。 同义词词典需要以下格式的配置文件:

# this is a comment
sample word(s) : indexed word(s)
more sample word(s) : more indexed word(s)
...

其中冒号(:)符号充当短语及其替换之间的分隔符。

同义词词典使用子词典(在词典的配置中指定)来在检查词组匹配之前规范化输入文本。 只能选择一个子字典。 如果子字典无法识别单词,则会报告错误。 在这种情况下,您应该删除单词的使用或教它关于它的子字典。 您可以在索引单词的开头放置一个星号(*)以跳过对其应用子字典,但所有样本单词必须为子字典所知。

如果存在多个与输入匹配的短语,则同义词词典选择最长匹配,并且通过使用最后定义来断开关系。

无法指定子字典识别的特定停止词; 改为使用?标记任何停止词可以出现的位置。 例如,假设athe根据子字典是停止词:

? one ? two : swsw

匹配a one the twothe one a two; 两者都将被swsw取代。

由于同义词词典具有识别短语的能力,因此它必须记住其状态并与解析器交互。 同义词词典使用这些分配来检查它是否应该处理下一个单词或停止累积。 必须仔细配置同义词词典。 例如,如果分配同义词词典仅处理asciiword token,那么像one 7一样的同义词词典定义将不起作用,因为token类型uint未分配给同义词词典。

CAUTION:
在索引期间使用同义词,因此同义词词典参数的任何更改都需要重新索引。 对于大多数其他字典类型,添加或删除停止词等小的更改不会强制重新编制索引。

同义词库配置

要定义新的同义词词典,请使用thesaurus模板。例如:

CREATE TEXT SEARCH DICTIONARY thesaurus_simple (
    TEMPLATE = thesaurus,
    DictFile = mythesaurus,
    Dictionary = pg_catalog.english_stem
);

其中:

  • thesaurus_simple是新的词典名称
  • mythesaurus是同义词库配置文件的基本名称。 (它的全名是$SHAREDIR/tsearch_data/mythesaurus.ths,其中$SHAREDIR表示安装共享数据目录。)
  • pg_catalog.english_stem是用于词库规范化的子字典(这里是一个Snowball英语词干分析器)。 请注意,subdictionary将具有自己的配置(例如,停止词),此处未显示。

现在可以将同义词词典thesaurus_simple绑定到配置中的所需token类型,例如:

ALTER TEXT SEARCH CONFIGURATION russian
    ALTER MAPPING FOR asciiword, asciihword, hword_asciipart
    WITH thesaurus_simple;

词库示例

考虑一个简单的天文词库thesaurus_astro,其中包含一些天文单词组合:

supernovae stars : sn
crab nebulae : crab

下面我们创建一个字典并将一些token类型绑定到天文词库和英语词干分析器:

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;

现在我们可以看到它是如何工作的。 ts_lexize对于测试同义词库并不是非常有用,因为它将其输入视为单个token。 相反,我们可以使用plainto_tsqueryto_tsvector,它们会将输入字符串分成多个token:

SELECT plainto_tsquery('supernova star');
 plainto_tsquery
-----------------
 'sn'

SELECT to_tsvector('supernova star');
 to_tsvector
-------------
 'sn':1

原则上,如果引用参数,可以使用to_tsquery

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

请注意,supernova starthesaurus_astro中的supernovae stars相匹配, 因为我们在同义词定义中指定了english_stem提取器。 提取器去掉了es

要索引原始短语以及替换,只需将其包含在定义的右侧部分:

supernovae stars : sn supernovae stars

SELECT plainto_tsquery('supernova star');
       plainto_tsquery
-----------------------------
 'sn' & 'supernova' & 'star'

Ispell字典

Ispell字典模板支持形态词典,可以将单词的许多不同语言形式归一化为相同的词位。 例如,英语Ispell字典可以匹配搜索项bank的所有词形组合和变化, 例如bankingbankedbanksbanks'和bank's

标准Greenplum数据库分发不包含任何Ispell配置文件。 Ispell提供大量语言的字典。 此外,还支持一些更现代的字典文件格式 - MySpell(OO < 2.0.1) 和Hunspell(OO> = 2.0.2)。 OpenOffice Wiki上提供了大量字典。

要创建Ispell字典,请使用内置ispell模板并指定几个参数:

CREATE TEXT SEARCH DICTIONARY english_ispell (
    TEMPLATE = ispell,
    DictFile = english,
    AffFile = english,
    StopWords = english
);

这里,DictFileAffFileStopWords指定字典,词缀和停止词文件的基本名称。 停止词文件具有与上述simple词典类型相同的格式。 此处未指定其他文件的格式,但可从上述网站获取。

Ispell字典通常识别一组有限的单词,因此应该跟着另一个更广泛的字典; 例如,一个可以识别一切的Snowball字典。

Ispell词典支持分裂复合词; 一个有用的功能。 请注意,词缀文件应使用compoundwords controlled语句指定一个特殊标志,该语句标记可以参与复合词形成的词典单词:

compoundwords  controlled z

以下是挪威语的一些示例:

SELECT ts_lexize('norwegian_ispell', 'overbuljongterningpakkmesterassistent');
   {over,buljong,terning,pakk,mester,assistent}
SELECT ts_lexize('norwegian_ispell', 'sjokoladefabrikk');
   {sjokoladefabrikk,sjokolade,fabrikk}
Note:

MySpell不支持复合词。 Hunspell对复合词有着复杂的支持。 目前,Greenplum数据库仅实现了Hunspell的基本复合词操作。

SnowBall词典

Snowball词典模板基于Martin Porter的一个项目,他是流行的Porter英语词干算法的发明者。 Snowball现在为许多语言提供词干算法(有关更多信息,请参阅Snowball站点)。 每种算法都理解如何将单词的常见变体形式减少到其语言中的基础或词干拼写。 Snowball字典需要一个语言参数来识别要使用的词干分析器,并且可以选择指定一个停止词文件名,该名称提供要删除的单词列表。 (Greenplum数据库的标准停止词列表也由Snowball项目提供。) 例如,有一个内置的定义等效于

CREATE TEXT SEARCH DICTIONARY english_stem (
    TEMPLATE = snowball,
    Language = english,
    StopWords = english
);

停止词文件格式与已经说明的相同。

Snowball字典可以识别所有内容,无论它是否能够简化单词,因此它应该放在字典列表的末尾。 在任何其他字典之前使用它是没用的,因为token永远不会通过它传递到下一个字典。