扩展或收缩

synonym-formats 中,我们看到了可以通过 简单扩展简单收缩 、或类型扩展 来指明同义词规则。 本章节我们将在这三者间做个权衡比较。

TIP: 本节仅处理单词同义词。多词同义词又增添了一层复杂性,在 multi-word-synonyms 中,我们将会讨论。

简单扩展

通过 简单扩展 ,我们可以把同义词列表中的任意一个词扩展成同义词列表 所有 的词:

  1. "jump,hop,leap"

扩展可以应用在索引阶段或查询阶段。两者都有优点 (⬆)︎ 和缺点 (⬇)︎。到底要在哪个阶段使用,则取决于性能与灵活性:

索引 查询
索引的大小 ⬇︎ 大索引。因为所有的同义词都会被索引,所以索引的大小相对会变大一些。 ⬆︎ 正常大小。
关联 ⬇︎ 所有同义词都有相同的 IDF(至于什么是 IDF ,参见 relevance-intro),这意味着通用的词和较常用的词都拥有着相同的权重。 ⬆︎ 每个同义词 IDF 都和原来一样。
性能 ⬆︎ 查询只需要找到查询字符串中指定单个词项。 ⬇︎ 对一个词项的查询重写来查找所有的同义词,从而降低性能。
灵活性 ⬇︎ 同义词规则不能改变现有的文件。对于有影响的新规则,现有的文件都要重建(注:重新索引一次文档)。 ⬆︎ 同义词规则可以更新不需要索引文件。

简单收缩

简单收缩 ,把左边的多个同义词映射到了右边的单个词:

  1. "leap,hop => jump"

它必须同时应用于索引和查询阶段,以确保查询词项映射到索引中存在的同一个值。

相对于简单扩展方法,这种方法也有一些优点和一些缺点:

索引的大小

⬆︎ 索引大小是正常的,因为只有单一词项被索引。

关联

⬇︎ 所有词项的 IDF 是一样的,所以你不能区分比较常用的词、不常用的单词。

性能

⬆︎ 查询只需要在索引中找到单词的出现。

灵活性

⬆︎ 新同义词可以添加到规则的左侧并在查询阶段使用。例如,我们想添加 bound 到先前指定的同义词规则中。那么下面的规则将作用于包含 bound 的查询或包含 bound 的文档索引:

  1. "leap,hop,bound => jump"

似乎对旧有的文档不起作用是么?其实我们可以把上面这个同义词规则改写下,以便对旧有文档同样起作用:

  1. "leap,hop,bound => jump,bound"

当你重建索引文件,你可以恢复到上面的规则(注: leap,hop,bound => jump )来获得查询单个词项的性能优势(注:因为上面那个规则相比这个而言,查询阶段就只要查询一个词了)。

类型扩展

类型扩展是完全不同于简单收缩或扩张,并不是平等看待所有的同义词,而是扩大了词的意义,使被拓展的词更为通用。以这些规则为例:

  1. "cat => cat,pet",
  2. "kitten => kitten,cat,pet",
  3. "dog => dog,pet"
  4. "puppy => puppy,dog,pet"

通过在索引阶段使用类型扩展:

  • 一个关于 kitten 的查询会发现关于 kittens 的文档。
  • 查询一个 cat 会找到关于 kittens 和 cats 的文档。
  • 一个 pet 的查询将发现有关的 kittens、cats、puppies、dogs 或者 pets 的文档。

或者在查询阶段使用类型扩展, kitten 的查询结果就会被拓展成涉及到 kittens、cats、dogs。

您也可以有两全其美的办法,通过在索引阶段应用类型扩展同义词规则,以确保类型在索引中存在。然后,在查询阶段, 你可以选择不采用同义词(使 kitten 查询只返回 kittens 的文件)或采用同义词, kitten 的查询操作就会返回包括 kittens、cats、pets(也包括 dogs 和 puppies)的相关结果。

前面的示例规则,对 kitten 的 IDF 将是正确的,而 catpet 的 IDF 将会被 Elasticsearch 降权。然而, 这是对你有利的,当一个针对 kitten 的查询被拓展成了针对 kitten OR cat OR pet 的查询, 那么 kitten 相关的文档就应该排在最上方,其次是 cat 的文件, pet 的文件将被排在最底部。