12.6. Dictionaries

字典用于消除搜索中不应该考虑的单词(停用词),并标准化单词,以使同一单词的不同派生形式匹配。成功的标准化单词称为* lexeme *。除了提高搜索质量外,标准化和停用词的删除还减少了文档的tsvector表示的大小,从而提高了性能。规范化并不总是具有语言含义,通常取决于应用程序语义。

标准化的一些示例:

  • 语言-Ispell 词典尝试将 Importing 单词减少为规范化形式;词干词典删除单词结尾

  • 可以规范化 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

  • 颜色名称可以用其十六进制值替换,例如red, green, blue, magenta -> FF0000, 00FF00, 0000FF, FF00FF

  • 如果为数字编制索引,我们可以删除一些小数位数以减小可能的数字范围,例如,如果小数点后仅保留两位数字,则* 3.14 * 159265359,* 3.14 * 15926,* 3.14 *将是相同的。

字典是一个程序,它接受令牌作为 Importing 并返回:

  • 如果字典知道 Importing 令牌,则为一组词素(请注意,一个令牌可以产生多个词素)

  • 设置了TSL_FILTER标志的单个词素,以将新的令牌替换为要传递给后续词典的原始令牌(执行此操作的字典称为过滤字典)

  • 如果字典知道令牌,则为空数组,但这是一个停用词

  • NULL如果字典无法识别 Importing 令牌

PostgreSQL 提供了许多语言的 sched 义词典。还有一些 sched 义的模板可用于创建带有自定义参数的新字典。每个 sched 义的词典模板描述如下。如果没有合适的现有模板,则可以创建新模板。有关示例,请参见 PostgreSQL 发行版的contrib/区域。

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

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

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

过滤字典可以放置在列表中的任何地方,除非结尾没用。过滤字典可用于部分标准化单词,以简化后续字典的工作。例如,可以使用过滤字典从重音字母中删除重音,就像unaccent模块所做的那样。

12 .6.1. 停用词

停用词是非常常见的词,几乎出现在每个文档中,并且没有歧视价值。因此,在全文搜索的上下文中可以忽略它们。例如,每个英文文本都包含athe之类的单词,因此将它们存储在索引中是没有用的。但是,停用词确实会影响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词干首先检查停用词列表。行为不同的原因是试图降低噪音。

12 .6.2. 简单字典

simple字典模板通过将 Importing 令牌转换为小写并针对停用词文件进行检查来进行操作。如果在文件中找到它,则返回一个空数组,从而导致令牌被丢弃。如果不是,则将单词的小写形式作为规范化的词素返回。或者,可以将词典配置为将无法识别的单词报告为无法识别,从而将其传递给列表中的下一个词典。

这是使用simple模板的字典定义的示例:

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

english是停用词文件的基本名称。该文件的全名将为$SHAREDIR/tsearch_data/english.stop,其中$SHAREDIR表示 PostgreSQL 安装的共享数据目录,通常为/usr/local/share/postgresql(如果不确定,请使用pg_config --sharedir确定它)。文件格式只是单词列表,每行一个。空行和尾随空格将被忽略,大写字母将被折叠为小写字母,但是不会对文件内容进行任何其他处理。

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

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

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

如果在停用词文件中找不到NULL,则也可以选择返回NULL,而不是小写字母。通过将字典的Accept参数设置为false可以选择此行为。continue 示例:

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

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

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

使用默认设置Accept = true时,仅将simple词典放在词典列表的末尾很有用,因为它绝不会将任何令牌传递给后续词典。相反,Accept = false仅在至少存在以下一个词典时才有用。

Caution

大多数类型的词典都依赖于配置文件,例如停用词文件。这些文件必须以 UTF-8 编码存储。当将它们读入服务器时,它们将转换为实际的数据库编码(如果不同)。

Caution

通常,数据库会话在会话中首次使用时,只会读取一次字典配置文件。如果您修改配置文件,并想强制现有会话接收新内容,请在字典上发出ALTER TEXT SEARCH DICTIONARY命令。这可能是“虚拟”更新,实际上并未更改任何参数值。

12 .6.3. 同义词词典

该词典模板用于创建词典,以同义词代替单词。不支持短语(为此使用同义词库模板(Section 12.6.4))。同义词词典可用于克服语言问题,例如,防止英语词干词典将单词“ 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}

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

synonym模板还具有可选参数CaseSensitive,默认为false。当CaseSensitivefalse时,同义词文件中的单词与 Importing 令牌一样被折叠为小写。当为true时,单词和令牌不会折叠为小写形式,而是按原样进行比较。

星号(*)可以放在配置文件中同义词的末尾。这表明同义词是前缀。当在to_tsvector()中使用该条目时,将忽略星号,但在to_tsquery()中使用该条目时,结果将是带有前缀匹配标记的查询项目(请参见Section 12.3.2)。例如,假设我们在$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)

12 .6.4. 词库词典

词库词典(有时缩写为 TZ)是单词的集合,其中包含有关单词和短语之间关系的信息,例如,较宽泛的术语(BT),较窄的术语(NT),首选术语,非首选术语,相关术语,等等

基本上,词库词典将所有非首选术语替换为一个首选术语,并有选择地保留原始术语以供索引。 PostgreSQL 当前对同义词库词典的实现是对同义词词典的扩展,增加了* phrase *支持。同义词库字典需要以下格式的配置文件:

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

其中的冒号(:)作为短语和其替换之间的分隔符。

同义词词典在检查短语匹配之前,使用* subdictionary (在词典的配置中指定)对 Importing 文本进行规范化。只能选择一个子词典。如果子词典无法识别单词,则会报告错误。在这种情况下,您应该删除该词的使用或教它的附属词。您可以在已索引词的开头放置一个星号(*),以跳过对该词应用该词典的方法,但是所有*示例词必须是该词典知道的。

如果有多个词组与 Importing 匹配,则同义词词典选择最长的匹配项,并且使用最后的定义来 break 联系。

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

? one ? two : swsw

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

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

Caution

同义词库在索引编制过程中使用,因此同义词库字典参数的任何更改都需要重新索引。对于大多数其他字典类型,小的更改(例如添加或删除停用词)不会强制重新索引。

12 .6.4.1. 同义词库配置

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

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

Here:

  • thesaurus_simple是新词典的名称

  • mythesaurus是同义词库配置文件的基本名称。 (其全名将为$SHAREDIR/tsearch_data/mythesaurus.ths,其中$SHAREDIR表示安装共享数据目录.)

  • pg_catalog.english_stem是用于同义词库归一化的子词典(此处是 Snowball 英语词干)。请注意,该子词典将具有自己的配置(例如,停用词),此处未显示。

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

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

12 .6.4.2. 词库示例

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

supernovae stars : sn
crab nebulae : crab

在下面,我们创建一个字典,并将一些令牌类型绑定到一个天文词库和英语词干:

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对于测试同义词库不是很有用,因为它会将 Importing 视为单个令牌。相反,我们可以使用plainto_tsqueryto_tsvector将它们的 Importing 字符串分成多个令牌:

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'

12 .6.5. Ispell 字典

Ispell 词典模板支持* morphological dictionaries *,可以将单词的许多不同语言形式规范化为相同的词素。例如,英语 Ispell 词典可以匹配搜索词bank(例如bankingbankedbanksbanks'bank's)的所有变形和共轭。

标准 PostgreSQL 发行版不包含任何 Ispell 配置文件。 Ispell提供了多种语言的字典。此外,还支持一些更现代的词典文件格式-MySpell(OO< 2.0.1) and Hunspell (OO > = 2.0.2)。 OpenOffice Wiki上有大量词典。

要创建 Ispell 词典,请执行以下步骤:

  • 下载字典配置文件。 OpenOfficeextensions 文件具有.oxtextensions。有必要提取.aff.dic文件,并将 extensions 更改为.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目录

  • 使用以下命令将文件加载到 PostgreSQL 中:

CREATE TEXT SEARCH DICTIONARY english_hunspell (
    TEMPLATE = ispell,
    DictFile = en_us,
    AffFile = en_us,
    Stopwords = english);

在这里,DictFileAffFileStopWords指定字典,词缀和停用词文件的基本名称。停用词文件的格式与上面针对simple字典类型说明的格式相同。其他文件的格式未在此处指定,但可以从上述网站上获得。

Ispell 词典通常只能识别有限的一组单词,因此应紧随其后的是另一个更广泛的词典。例如,可以识别所有内容的 Snowball 词典。

Ispell 的.affix文件具有以下结构:

prefixes
flag *A:
    .           >   RE      # As in enter > reenter
suffixes
flag T:
    E           >   ST      # As in late > latest
    [^AEIOU]Y   >   -Y,IEST # As in dirty > dirtiest
    [AEIOU]Y    >   EST     # As in gray > grayest
    [^EY]       >   EST     # As in small > smallest

.dict文件具有以下结构:

lapse/ADGRS
lard/DGRS
large/PRTY
lark/MRS

.dict文件的格式为:

basic_form/affix_class_name

.affix文件中,每个词缀标志均以以下格式描述:

condition > [-stripping_letters,] adding_affix

这里,条件的格式类似于正则表达式的格式。它可以使用分组[...][^...]。例如,[AEIOU]Y表示单词的最后一个字母是"y",倒数第二个字母是"a""e""i""o""u"[^EY]表示最后一个字母既不是"e"也不是"y"

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}

MySpell 格式是 Hunspell 的子集。 Hunspell 的.affix文件具有以下结构:

PFX A Y 1
PFX A   0     re         .
SFX T N 4
SFX T   0     st         e
SFX T   y     iest       [^aeiou]y
SFX T   0     est        [aeiou]y
SFX T   0     est        [^ey]

词缀类的第一行是标题。Headers 规则字段在标题后列出:

  • 参数名称(PFX 或 SFX)

  • 标志(词缀类的名称)

  • 从单词的开头(前缀)或结尾(后缀)剥离字符

  • adding affix

  • 格式类似于正则表达式格式的条件。

.dict文件类似于 Ispell 的.dict文件:

larder/M
lardy/RT
large/RSPMYT
largehearted

Note

MySpell 不支持复合词。 Hunspell 对复合词有完善的支持。目前,PostgreSQL 仅实现 Hunspell 的基本复合词操作。

12 .6.6. 雪球字典

Snowball 词典模板基于 Martin Porter 的项目,Martin Porter 是流行的 Porter 的英语词干提取算法的发明者。 Snowball 现在提供了多种语言的词干算法(有关更多信息,请参见Snowball site)。每个算法都了解如何在其语言中将常见的变体形式的单词减少为基础或词干的拼写。 Snowball 字典需要language参数来标识要使用的词干,并且可以选择指定stopword文件名,该文件名提供了要消除的单词列表。 (PostgreSQL 的标准停用词列表也由 Snowball 项目提供.)例如,有一个等效于的内置定义

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

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

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