ES索引,映射和分析
Elasticsearch中的字段类型可以分为两类:精确值和全文。精确值 如它们听起来那样精确。例如日期或者用户 ID,但字符串也可以表示精确值,例如用户名或邮箱地址。对于精确值来讲,Foo 和 foo 是不同的,2014 和 2014-09-15 也是不同的。另一方面,全文 是指文本数据(通常以人类容易识别的语言书写),例如一个推文的内容或一封邮件的内容。
精确值很容易查询。结果是二进制的:要么匹配查询,要么不匹配。查询全文数据要微妙的多。我们问的不只是“这个文档匹配查询吗”,而是“该文档匹配查询的程度有多大?”换句话说,该文档与给定查询的相关性如何?为了促进这类在全文域中的查询,Elasticsearch 首先 分析 文档,之后根据结果创建 倒排索引 ,分析然后建立索引是ES处理文档的方式。
倒排索引
Elasticsearch 使用一种称为 倒排索引 的结构,它适用于快速的全文搜索。一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表。ES会为每个字段建立一个倒排索引,每个倒排索引最基本的结构就是“keyword”和“Posting List”,Posting list就是一个int的数组,存储了所有符合某个term的文档id。
另外,这个倒排索引相比特定词项出现过的文档列表,会包含更多其它信息。它会保存每一个词项出现过的文档总数, 在对应的文档中一个具体词项出现的总次数,词项在文档中的顺序,每个文档的长度,所有文档的平均长度,等等。这些统计信息允许 Elasticsearch 决定哪些词比其它词更重要,哪些文档比其它文档更重要,这涉及到搜索相关性的内容。
在权威指南这本书中明确指出,ES的索引是有序(sorted)的,这里不同于innodb等数据库引擎采用的B-tree的数据结构,ES构建了一个不同于B-tree的Term Dictionary结构,通过二分查找的方式查找数据。
B-Tree通过减少磁盘寻道次数来提高查询性能,Elasticsearch也是采用同样的思路,直接通过内存查找term,不读磁盘,但是如果term太多,term dictionary也会很大,放内存不现实,于是有了Term Index,就像字典里的索引页一样,A开头的有哪些term,分别在哪页,可以理解term index是一颗树:
image.png
这棵树不会包含所有的term,它包含的是term的一些前缀。通过term index可以快速地定位到term dictionary的某个offset,然后从这个位置再往后顺序查找。所以term index不需要存下所有的term,而仅仅是他们的一些前缀与Term Dictionary的block之间的映射关系,再结合FST(Finite State Transducers)的压缩技术,可以使term index缓存到内存中。从term index查到对应的term dictionary的block位置之后,再去磁盘上找term,大大减少了磁盘随机读的次数。
term会通过FST压缩技术(bitmap也是这种思想),posting list也会压缩,压缩方法是将posting list排序,然后将大数映射成小数,再用bitmap存储,5.0之后ES采用了Roaring bitmaps的方式,将posting list按照65535为界限分块,比如第一块所包含的文档id范围在065535之间,第二块的id范围是65536131071,以此类推。再用<商,余数>的组合表示每一组id,这样每组里的id范围都在0~65535内了,剩下的就好办了,既然每组id不会变得无限大,那么我们就可以通过最有效的方式对这里的id存储。
上面是关于单个索引的构建与查询,对于多个索引的联合查询,倒排索引如何满足快速查询的要求呢?最简单的当然是在每个索引里查取交集。还可以:
- 利用跳表(Skip list)的数据结构快速做“与”运算,或者
- 利用上面提到的bitset按位“与”
多个索引本身就是一个跳表的结构,可以通过跳表搜索的方式找到文档id。
如果使用bitset,就很直观了,直接按位与,得到的结果就是最后的交集。
分析与分析器
分析 包含下面的过程:
- 首先,将一块文本分成适合于倒排索引的独立的 词条 ,
- 之后,将这些词条统一化为标准格式以提高它们的“可搜索性”,或者 recall
分析器执行上面的工作。 分析器 实际上是将三个功能封装到了一个包里: - 字符过滤器 首先,字符串按顺序通过每个 字符过滤器 。他们的任务是在分词前整理字符串。一个字符过滤器可以用来去掉HTML,或者将 & 转化成
and
。 - 分词器 其次,字符串被 分词器 分为单个的词条。一个简单的分词器遇到空格和标点的时候,可能会将文本拆分成词条。
- Token 过滤器 最后,词条按顺序通过每个 token 过滤器 。这个过程可能会改变词条(例如,小写化 Quick ),删除词条(例如, 像 a
,
and,
the 等无用词),或者增加词条(例如,像 jump 和 leap 这种同义词)。
Elasticsearch提供了开箱即用的字符过滤器、分词器和token 过滤器。 这些可以组合起来形成自定义的分析器以用于不同的目的。
当我们 索引 一个文档,它的全文域被分析成词条以用来创建倒排索引。 但是,当我们在全文域 搜索 的时候,我们需要将查询字符串通过 相同的分析过程 ,以保证我们搜索的词条格式与索引中的词条格式一致。
全文查询,理解每个域是如何定义的,因此它们可以做 正确的事:
- 当你查询一个 全文 域时, 会对查询字符串应用相同的分析器,以产生正确的搜索词条列表。
- 当你查询一个 精确值 域时,不会分析查询字符串, 而是搜索你指定的精确值。
映射
为了能够将时间域视为时间,数字域视为数字,字符串域视为全文或精确值字符串, Elasticsearch 需要知道每个域中数据的类型。这个信息包含在映射中。映射就是指明字段类型。
如 数据输入和输出 中解释的, 索引中每个文档都有 类型 。每种类型都有它自己的 映射 ,或者 模式定义。映射定义了类型中的域,每个域的数据类型,以及Elasticsearch如何处理这些域。映射也用于配置与类型有关的元数据。
尽管在很多情况下基本域数据类型 已经够用,但你经常需要为单独域自定义映射 ,特别是字符串域。自定义映射允许你执行下面的操作:
- 全文字符串域和精确值字符串域的区别
- 使用特定语言分析器
- 优化域以适应部分匹配
- 指定自定义数据格式
type:字段数据类型,ES支持的基本数据类型:string,byte, short, integer, long,float, double,boolean,date
index:analyzed,首先分析字符串,然后索引它。换句话说,以全文索引这个域。not_analyzed,索引这个域,所以它能够被搜索,但索引的是精确值。不会对它进行分析。no,不索引这个域。这个域不会被搜索到。(string默认是analyzed)
analyzer:对于 analyzed 字符串域,用 analyzer 属性指定在搜索和索引时使用的分析器。默认, Elasticsearch 使用 standard 分析器, 但你可以指定一个内置的分析器替代它,例如 whitespace 、 simple 和 english
,也可以使用自定义的分析器
当你首次 创建一个索引的时候,可以指定类型的映射。你也可以使用 /mapping 为新类型(或者为存在的类型更新映射)增加映射。尽管你可以 *增加 一个存在的映射,你不能 修改* 存在的域映射。如果一个域的映射已经存在,那么该域的数据可能已经被索引。如果你意图修改这个域的映射,索引的数据可能会出错,不能被正常的搜索。
0人点赞
ElasticSearch
作者:黍苗
链接:https://www.jianshu.com/p/2e6af6398161
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
以上是 ES索引,映射和分析 的全部内容, 来源链接: utcz.com/z/512249.html