精确值vs全文
es中的数据主要分为两类:精确值和全文。
精确值,例如指定的id、邮箱地址、用户名,都属于精确值查询,Hello和hello是不同的。
全文,指的是文本数据(通常以人类容易识别的语言书写),例如一条微博的内容或者一封邮件的内容。
全文通常指非结构化的数据,自然语言是高度结构化的,但是自然语言的规则是复杂的,计算机通常难以正确解析。例如下面这句话到底指的是月份还是人?
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,匹配jumped,jumps,jumping;
为了能够达成这类全文查询,es首先分析文档,之后根据结果创建倒排索引。
倒排索引
es中使用了一种被称为倒排索引的结构,它用于快速的全文搜索,一个倒排索引由文档中所有不重复词的列表构成。
例如,我们有两个文档,每个文档的content域包含如下内容:
- The quick brown fox jumped over the lazy dog
- Quick brown foxes leap over lazy dogs in summer
为了创建倒排索引,我们会将每个文档的content域拆分成单独的词(我们把它称为词条或者tokens),创建一个包含所有不重复词条的排序列表,然后列出每个词条出现在哪个文档。结果如下所示:
如果我们想搜索
quick brown,我们只需要查找包含每个词条的文档:
两个文档都匹配,但是文档1的匹配度更高,如果仅计算匹配词条数量的简单 相似性算法,那么对于查询的相关性来说,文档1更加符合。
目前上面这种倒排索引还存在一些问题:
Quick和quick以独立的词条出现,但是用户可能认为他们的相同的词。fox和foxs,dog和dogs,拥有相同的词根。jumped和leap, 尽管没有相同的词根,但他们的意思很相近。他们是同义词。
使用前面的索引搜索 +Quick +fox 不会得到任何匹配文档。(记住,+ 前缀表明这个词必须存在。)只有同时出现 Quick 和 fox 的文档才满足这个查询条件,但是第一个文档包含 quick fox ,第二个文档包含 Quick foxes 。
我们可以做出一些优化,将词条规范为标准模式,虽然找到的文档和用户搜索的词条不完全一致,但具有一定的相关性。例如:
Quick小写化为quick;foxes提取词干为fox;jumped和leap是同义词,可以索引为相同的单词jump。
现在的索引:
我们使用+Quick +fox搜索仍会失败,因为在索引中已经没有Quick了,因此我们对搜索的字符串的格式应该使用与content域的格式保持一致,使用+quick +fox,这样两个文档会匹配。
分析与分析器
分析主要包含以下过程:
- 将一块文本分成适合于倒排索引的独立词条。
- 将这些独立词条统一化为标准格式以提高它们的可搜索性。
分析器执行上面的流程。
分析器中有三个功能:字符过滤器去掉无效的字符或者转义响应的字符,然后通过分词器,将字符串拆分为单个的词条,最后通过Token过滤器增加、删除、改变词条。
字符过滤器
字符串按照顺序通过每个字符过滤器。它们的作用就是在分词前整理字符串,用来去掉HTML,或者将&转换成and。
分词器
字符串被分词器分为单个词条。
Token过滤器
最后,词条按顺序通过每个 Token过滤器。过程中可能会改变词条(例如,小写化Quick),删除词条(例如, 像 a, and, the 等无用词),或者增加词条(例如,像 jump 和 leap 这种同义词)。
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
我们可以看到原本的transparent、calling和set_trans已经变为词根格式。
全文域和精确值域
当我们索引一个文档,它的全文域被分析成词条以用来创建倒排索引。当我们在全文域搜索的时候,我们需要将查询字符串通过相同的分析器,以保证搜索的词条格式与索引中的词条格式保持一致。
- 当你查询一个全文域时,会对查询字符串应用相同的分析器,以产生正确的搜索词条列表。
- 当你查询一个精确值时,不会分析查询字符串,而是搜索你指定的精确值。