【es】映射与分析

127 阅读6分钟

精确值vs全文

es中的数据主要分为两类:精确值和全文。

精确值,例如指定的id、邮箱地址、用户名,都属于精确值查询,Hellohello是不同的。

全文,指的是文本数据(通常以人类容易识别的语言书写),例如一条微博的内容或者一封邮件的内容。

全文通常指非结构化的数据,自然语言是高度结构化的,但是自然语言的规则是复杂的,计算机通常难以正确解析。例如下面这句话到底指的是月份还是人?

May is fun but June bores me.

精确值很容易查询,要么匹配,要么不匹配,我们很容易用SQL表示:

WHERE name    = "John Smith"
  AND user_id = 2
  AND date    > "2014-09-15"

查询全文数据则微妙的多,不仅需要匹配查询,而且还有相关性的分析,该文档与我要查询的内容的相关性有多大?不仅如此,我们还希望搜索的结果能够理解我们的意图

  • 搜索UK,返回包含United Kindom的文档;
  • 搜索jump,匹配jumpedjumpsjumping

为了能够达成这类全文查询,es首先分析文档,之后根据结果创建倒排索引

倒排索引

es中使用了一种被称为倒排索引的结构,它用于快速的全文搜索,一个倒排索引由文档中所有不重复词的列表构成。

例如,我们有两个文档,每个文档的content域包含如下内容:

  1. The quick brown fox jumped over the lazy dog
  2. Quick brown foxes leap over lazy dogs in summer

为了创建倒排索引,我们会将每个文档的content域拆分成单独的词(我们把它称为词条或者tokens),创建一个包含所有不重复词条的排序列表,然后列出每个词条出现在哪个文档。结果如下所示:

image-20220913144955879.png 如果我们想搜索quick brown,我们只需要查找包含每个词条的文档:

image-20220913145143317.png

两个文档都匹配,但是文档1的匹配度更高,如果仅计算匹配词条数量的简单 相似性算法,那么对于查询的相关性来说,文档1更加符合。

目前上面这种倒排索引还存在一些问题:

  • Quickquick以独立的词条出现,但是用户可能认为他们的相同的词。
  • foxfoxsdogdogs,拥有相同的词根。
  • jumpedleap, 尽管没有相同的词根,但他们的意思很相近。他们是同义词。

使用前面的索引搜索 +Quick +fox 不会得到任何匹配文档。(记住,+ 前缀表明这个词必须存在。)只有同时出现 Quickfox 的文档才满足这个查询条件,但是第一个文档包含 quick fox ,第二个文档包含 Quick foxes

我们可以做出一些优化,将词条规范为标准模式,虽然找到的文档和用户搜索的词条不完全一致,但具有一定的相关性。例如:

  • Quick小写化为quick
  • foxes提取词干为fox
  • jumpedleap 是同义词,可以索引为相同的单词 jump

现在的索引:

image-20220913150445940.png

我们使用+Quick +fox搜索仍会失败,因为在索引中已经没有Quick了,因此我们对搜索的字符串的格式应该使用与content域的格式保持一致,使用+quick +fox,这样两个文档会匹配。

分析与分析器

分析主要包含以下过程:

  • 将一块文本分成适合于倒排索引的独立词条。
  • 将这些独立词条统一化为标准格式以提高它们的可搜索性。

分析器执行上面的流程。

分析器中有三个功能:字符过滤器去掉无效的字符或者转义响应的字符,然后通过分词器,将字符串拆分为单个的词条,最后通过Token过滤器增加、删除、改变词条。

字符过滤器

字符串按照顺序通过每个字符过滤器。它们的作用就是在分词前整理字符串,用来去掉HTML,或者将&转换成and

分词器

字符串被分词器分为单个词条。

Token过滤器

最后,词条按顺序通过每个 Token过滤器。过程中可能会改变词条(例如,小写化Quick),删除词条(例如, 像 aandthe 等无用词),或者增加词条(例如,像 jumpleap 这种同义词)。

es提供了开箱即用的字符过滤器、分词器和token过滤器。我们可以将这些自行组合起来形成自定义的分析器用于不同目的。

内置分析器

es附带了可以直接使用的预包装分析器,我们来看看几个最重要的分析器,从例子中观察它们之间的差异。

"Set the shape to semi-transparent by calling set_trans(5)"

标准分析器

标准分析器是es默认使用的分析器。它是分析各种语言文本最常用的选择。它根据Unicode 联盟定义的 单词边界划分文本,删除绝大部分标点,最后将词条小写。它会产生以下词条:

set, the, shape, to, semi, transparent, by, calling, set_trans, 5

简单分析器

简单分析器在任何不是字母的地方分隔文本,词条小写,它会产生以下词条:

set, the, shape, to, semi, transparent, by, calling, set, trans

空格分析器

空格分析器在空格的地方划分文本,它会产生以下词条:

Set, the, shape, to, semi-transparent, by, calling, set_trans(5)

语言分析器

特定的语言分析器可用于很多语言,它们可以考虑指定语言的特点。例如,英语分析器附带了一组英语无用词(例如and或者the,它们对相关性没有影响),它们会被删除。这个分词器可以提取英语单词的词干。

英语分词器会产生下面的词条:

set, shape, semi, transpar, call, set_tran, 5

我们可以看到原本的transparentcallingset_trans已经变为词根格式。

全文域和精确值域

当我们索引一个文档,它的全文域被分析成词条以用来创建倒排索引。当我们在全文域搜索的时候,我们需要将查询字符串通过相同的分析器以保证搜索的词条格式与索引中的词条格式保持一致。

  • 当你查询一个全文域时,会对查询字符串应用相同的分析器,以产生正确的搜索词条列表。
  • 当你查询一个精确值时,不会分析查询字符串,而是搜索你指定的精确值。