Elasticsearch——分词及映射(五)

前言

在对数据库的数据进行检索时,我们是以表映射字段内容,条件语句的遍量需要是字段精确值或者字段相连的一部分。

而Elasticsearch则不同,将具体内容进行分析和倒排索引,每个索引可以与多个文档作映射,索引内容可以为精确值,也可以为进行分析处理后的符合我们要求的值。

比如 我们通过谷歌查询springboot 和 SpringBoot,都可以检索到一系列文章,而且大体相同。

精确值和全文

精确值 如它们听起来那样精确。例如日期或者用户 ID,但字符串也可以表示精确值,例如用户名或邮箱地址。对于精确值来讲,Foo 和 foo 是不同的,2014 和 2014-09-15 也是不同的。

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

精确值很容易查询。结果是二进制的:要么匹配查询,要么不匹配。这种查询很容易用 SQL 表示:

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

全文我们更希望做到相关查询,不是说查询条件多一个字或者少一个字就查询不到,而是希望搜索引擎“理解”我们的意思。

  • 搜索 UK ,会返回包含 United Kindom 的文档。
  • 搜索 jump ,会匹配 jumped , jumps , jumping ,甚至是 leap 。

倒排索引

Elasticsearch 使用一种称为 倒排索引 的结构,它适用于快速的全文搜索。一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表。

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

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

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

Term Doc_1 Doc_2
Quick X
The X
brown X X
dog X
dogs X
fox X
foxes X
in X
jumped X
lazy X X
leap X
over X X
quick X
summer X
the X

现在,如果我们想搜索 quick brown ,我们只需要查找包含每个词条的文档:

Term Doc_1 Doc_2
brown X X
quick X
Total 2 1

两个文档都匹配,但是第一个文档比第二个匹配度更高。如果我们使用仅计算匹配词条数量的简单 相似性算法 ,那么,我们可以说,对于我们查询的相关性来讲,第一个文档比第二个文档更佳。

但是我想要用quick就可以查到Quick和quick相关的文档,dog能够查到dog和dogs。jumped 和 leap, 尽管没有相同的词根,但他们的意思很相近。他们是同义词。

如果我们将词条规范为标准模式,那么我们可以找到与用户搜索的词条不完全一致,但具有足够相关性的文档。例如:

  • Quick 可以小写化为 quick 。
  • foxes 可以 词干提取 –变为词根的格式– 为 fox 。类似的, dogs 可以为提取为 dog 。
  • jumped 和 leap 是同义词,可以索引为相同的单词 jump 。

但是这样我们查询Quick+fox还是无法达到要求,因为在我们的索引中,已经没有 Quick 了。但是,如果我们对搜索的字符串使用与 content 域相同的标准化规则,会变成查询 +quick +fox ,这样两个文档都会匹配!

这非常重要。你只能搜索在索引中出现的词条,所以索引文本和查询字符串必须标准化为相同的格式。

而分词和标准化的过程称为 分析。

分析

分析 包含下面的过程:

  • 首先,将一块文本分成适合于倒排索引的独立的 词条 ,
  • 之后,将这些词条统一化为标准格式以提高它们的“可搜索性”,或者 recall

这些都要通过分析器来完成。

分析器 实际上是将三个功能封装到了一个包里:

  1. 字符过滤器

    首先,字符串按顺序通过每个 字符过滤器 。他们的任务是在分词前整理字符串。一个字符过滤器可以用来去掉HTML,或者将 & 转化成 and。

  2. 分词器

    其次,字符串被 分词器 分为单个的词条。一个简单的分词器遇到空格和标点的时候,可能会将文本拆分成词条。

  3. Token 过滤器

    最后,词条按顺序通过每个 token 过滤器 。这个过程可能会改变词条(例如,小写化 Quick ),删除词条(例如, 像 a, and, the 等无用词),或者增加词条(例如,像 jump 和 leap 这种同义词)。

Elasticsearch附带了可以直接使用的预包装的分析器。

  1. 标准分析器

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

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

  2. 简单分析器

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

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

  3. 空格分析器

    空格分析器在空格的地方划分文本。它会产生

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

  4. 语言分析器

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

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

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

    ss注意看 transparent、 calling 和 set_trans 已经变为词根格式。

什么时候用到分析器?

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

全文查询,理解每个域是如何定义的,因此它们可以做正确的事:

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

指定分析器

当Elasticsearch在你的文档中检测到一个新的字符串域,它会自动设置其为一个全文 字符串 域,使用 标准 分析器对它进行分析。

你不希望总是这样。可能你想使用一个不同的分析器,适用于你的数据使用的语言。有时候你想要一个字符串域就是一个字符串域—​不使用分析,直接索引你传入的精确值,例如用户ID或者一个内部的状态域或标签。

要做到这一点,我们必须手动指定这些域的映射。

通常我们只对String类型的域设置分析器,其他类型的域如Integer、date,通常使用精确查询。

string 域映射的两个最重要属性是 index 和 analyzer 。

index 属性控制怎样索引字符串。它可以是下面三个值:

  • analyzed 首先分析字符串,然后索引它。换句话说,以全文索引这个域。
  • not_analyzed 索引这个域,所以它能够被搜索,但索引的是精确值。不会对它进行分析。
  • no 不索引这个域。这个域不会被搜索到。

对于 analyzed 字符串域,用 analyzer 属性指定在搜索和索引时使用的分析器。

1
2
3
4
5
6
{
"tweet": {
"type": "string",
"analyzer": "english"
}
}

总结

只能添加域映射,而不能更改现有域的映射。如果一个域的映射已经存在,那么该域的数据可能已经被索引。如果你意图修改这个域的映射,索引的数据可能会出错,不能被正常的搜索。

文章目录
  1. 1. 前言
  2. 2. 精确值和全文
  3. 3. 倒排索引
  4. 4. 分析
  5. 5. 指定分析器
  6. 6. 总结
|