15_Elasticsearch 内部原理详细解析(下篇)

本文章收录于【Elasticsearch 系列】,将详细的讲解 Elasticsearch 整个大体系,包括但不限于ELK讲解、ES调优、海量数据处理等

一、什么是mapping

自动或手动为index中的type建立的一种数据结构和相关配置,简称为mapping。我们以下面的例子来说明什么是mapping。

插入几条数据,让es自动为我们建立一个索引

PUT /article/_doc/1
{
  "post_date": "2017-01-01",
  "title": "my first article",
  "content": "this is my fi  rst article in this website",
  "author_id": 11400
}

我们可以通过 GET article/_mapping 命令来查看es自动建立的mapping,从下图可以看出es会根据字段值的不同会给字段设置不同的值

533b1573888e484a2e1f2344858a67e7.png

dynamic mapping,自动为我们建立index,以及对应的mapping,mapping中包含了每个field对应的数据类型,以及如何分词等

当然我们也可以手动在创建数据之前,先创建index以及对应的mapping

二、精确匹配与全文搜索的对比分析

1、精确匹配(exact value)

Elasticsearch中的数据可以大致分为两种类型:精准匹配及全文文本

精准匹配是确定的,正如它的名字一样。精准匹配“Foo”和“foo”就并不相同。2021 和2021-09-15也不相同。

比如有个字段的值是2022-01-01,当通过精准匹配(exact value)搜索的时候,必须输入2022-01-01,才能搜索出来,如果你输入一个01,是搜索不出来的。

2、全文检索(full text)

全文文本从另一个角度来说是文本化的数据(常常以人类的语言书写),比如一篇推文(Twitter的文章)或邮件正文。

全文文本(full text)就不是说单纯的只是匹配完整的一个值,而是可以对值进行拆分词语后(分词)进行匹配,也可以通过缩写、时态、大小写、同义词等进行匹配。

比如:

(1)缩写 vs. 全程:cn vs china

(2)格式转化:like liked likes

(3)大小写:Tom vs tom

(4)同义词:like vs love

2017-01-01,2017 01 01,搜索2017,或者01,都可以搜索出来

china,搜索cn,也可以将china搜索出来

likes,搜索like,也可以将likes搜索出来

Tom,搜索tom,也可以将Tom搜索出来

like,搜索love,同义词,也可以将like搜索出来

三、倒排索引原理理解

假如我们有两个文档,他们分别是

doc1:I really liked my small dogs, and I think my mom also liked them.
doc2:He never liked any dogs, so I hope that my mom will not expect me to liked him.

我们来进行模拟分词以及倒排索引的建立。建立倒排索引的时候,会执行一个操作(normalization)。也就是说对拆分出的各个单词进行相应的处理,以提升后面搜索的时候能够搜索到相关联的文档的概率。

normalization简单来说就是在建立倒排索引时进行时态的转换,单复数的转换,同义词的转换,大小写的转换。比如:mom —> mother,liked —> like,small —> little,dogs —> dog。

建立倒排索引,加入normalization

b91d3d1250c12c52fb5c652f8493f7ab.png

当使用mother liked little dog搜索时,会先进行分词,然后进行normalization,就会把mother 转成 mom、like-->like、little--> little、dog-->dog。

搜索结果:doc1和doc2都会搜索出来

四、分词器的内部组成到底是什么,以及内置分词器的介绍

1、什么是分词器

分词器是Elasticsearch中很重要的一个组件,用来将一段文本分析成一个一个的词,Elasticsearch再根据这些词去做倒排索引。主要功能是做切分词语和normalization(提升recall召回率)

比如给你一段句子,然后将这段句子拆分成一个一个的单个的单词,同时对每个单词进行normalization(时态转换,单复数转换),分词器

recall召回率:搜索的时候,增加能够搜索到的结果的数量

2、分词器内部主要组成部分

分词器主要由三个部门组成:字符过滤器(character filter)、分词器(tokenizer)、token filter

  • character filter:在一段文本进行分词之前,先进行预处理。比如说最常见的就是,过滤html标签(<span>hello<span> 转换成 hello),& 转换成 and(I&you 转换成 I and you);

  • tokenizer:进行分词处置。比如hello you and me 进行分词之后 hello, you, and, me

  • token filter:进行normalization相关的一些操作。比如dogs转换成dog、liked转换成like、Tom转换成tom、a/the/an这种无意义的停用词直接干掉、mother转换成mom、small转换成little。

分词器非常重要,它能够将一段文本进行各种处理,最后处理好的结果才会拿去建立倒排索引。

2、elasticsearch内置分词器介绍

  • standard analyzer:标准分词器,是Elasticsearch中默认的分词器,可以拆分英文单词,大写字母统一转换成小写。

  • simple analyzer:按非字母的字符分词,例如:数字、标点符号、特殊字符等,会去掉非字母的词,大写字母统一转换成小写。

  • whitespace analyzer:简单按照空格进行分词,相当于按照空格split了一下,大写字母不会转换成小写。

  • stop analyzer:会去掉无意义的词,例如:the、a、an 等,大写字母统一转换成小写。

  • keyword analyzer:不拆分,整个文本当作一个词。

elasticsearch 中默认使用的分词器为standard。

下面用一个例子来说明在各个分词器中的表现

例子语句:Set the shape to semi-transparent by calling set_trans(5)

在各种分词器中的表现为

standard analyzer:set, the, shape, to, semi, transparent, by, calling, set_trans, 5

simple analyzer:set, the, shape, to, semi, transparent, by, calling, set, trans

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

language analyzer(特定的语言的分词器,比如说,英语分词器):set, shape, semi, transpar, call, set_tran, 5

五、query string的分词器

1、query string分词

query string必须和index建立时相同的analyzer进行分词,其对exact value和full text是区别对待的

比如我们有一个document,其中有一个field,包含的value是:hello you and me,建立倒排索引。我们要搜索这个document对应的index,搜索文本是hell me,这个搜索文本就是query string。

query string默认情况下es会使用它对应的field建立倒排索引时相同的分词器去进行分词,进行分词和normalization。只有这样才能实现正确的搜索

比如我们建立倒排索引的时候,将dogs --> dog,结果你搜索的时候,还是一个dogs,那不就搜索不到了吗?所以搜索的时候,那个dogs也必须变成dog才行。才能搜索到。

不同类型的field,可能有的就是full text,有的就是exact value

六、mapping 元数据详细讲解

1、什么是mapping

mapping是定义文档及其包含的字段如何存储和索引的过程。

mapping就是index的元数据,每个index都有一个自己的mapping,决定了数据类型,建立倒排索引的行为,还有进行搜索的行为例如等。

可以使用映射(mapping)来定义哪些字符串字段应被视为全文字段,哪些字段包含数字、日期或地理位置以及日期值的格式,还可以自定义规则来控制动态添加字段的映射。

ES的mapping类似于静态语言中的数据类型:声明一个变量为int类型的变量,以后这个变量都只能存储int类型的数据。一个number类型的mapping字段只能存储number类型的数据。

同语言的数据类型相比,mapping还有一些其他的含义,mapping不仅告诉ES一个field中是什么类型的值, 它还告诉ES如何索引数据以及数据是否能被搜索到。

当你的查询没有返回相应的数据,你的mapping很有可能有问题。当你拿不准的时候,直接检查你的mapping。

当我们向elasticsearch中插入一条数据时,es内部流程如下:

(1)往es里面直接插入数据,es会自动建立索引,同时建立type以及对应的mapping

(2)mapping中就自动定义了每个field的数据类型

(3)不同的数据类型(比如说text和date),可能有的是exact value,有的是full text

(4)exact value,在建立倒排索引的时候,分词的时候,是将整个值一起作为一个关键词建立到倒排索引中的;full text,会经历各种各样的处理,分词,normaliztion(时态转换,同义词转换,大小写转换),才会建立到倒排索引中

(5)同时呢,exact value和full text类型的field就决定了,在一个搜索过来的时候,对exact value field或者是full text field进行搜索的行为也是不一样的,会跟建立倒排索引的行为保持一致;比如说exact value搜索的时候,就是直接按照整个值进行匹配,full text query string,也会进行分词和normalization再去倒排索引中去搜索

(6)可以用es的dynamic mapping,让其自动建立mapping,包括自动设置数据类型;也可以提前手动创建index和type的mapping,自己对各个field进行设置,包括数据类型,包括索引行为,包括分词器,等等

2、mapping的核心数据类型以及dynamic mapping

(1)、核心的数据类型

mapping的核心数据类型分为:

简单类型:string、byte、short、integer、long、float、double、boolean、date;

对象类型:一种支持 JSON 分层性质的类型。例如 object或nested。

特殊类型:如geo_point, geo_shape, 或completion

(2)动态映射(dynamic mapping)

当我们插入一条数据时,如果这个索引在es中存在,es则会根据相应的规则帮我们动态映射到对应的mapping数据类型。

比如true或false会映射成boolean类型,123会映射成long类型,123.45映射成double类型,2017-01-01映射成date类型,"hello world" 映射成string(text)类型

(3)查看索引的mapping结构

GET article/_mapping

d0241d39a9720ceda87967a22bf0b525.png

3、手动建立和修改mapping以及定制string类型数据是否分词

(1)如何建立索引

允许分词:analyzed

不允许分词:not_analyzed

不能被索引和分词:no

只能创建index时手动建立mapping,或者新增field mapping,但是不能update field mapping

创建索引

PUT /article
{
  "mappings": {
      "properties": {
        "author_id": {
          "type": "long"
        },
        "title": {
          "type": "text",
          "analyzer": "english"
        },
        "content": {
          "type": "text"
        },
        "post_date": {
          "type": "date"
        }
      }
  }
}

(2)对mapping的各种操作

但是不能够修改mapping,修改mapping时会报错:index [article/F4pFl4TdQASTSN2y-kkgEA] already exists

197c0a9524d5346377ed72d2e4f0367d.png

但是可以新增字段,然后设置对应的数据类型

#新增mapping字段映射
PUT /article/_mapping
{
  "properties": {
    "createName": {
      "type": "keyword"
    }
  }
}

查看索引中所有字段的mapping映射

GET /article/_mapping

0ff0ae8faef74a0aa50ba0ad65c14077.png

查看索引单个字段的mapping映射

GET /article/_mapping/field/createName

bc51811a4617b403a04b1df6b9bc9340.png

(3)mapping复杂数据类型以及object类型

a、多值字段:multivalue field

{ "tags": [ "tag1", "tag2" ]}

建立索引时与string是一样的,数据类型不能混

b、空字段:empty field

null,[],[null]

c、对象字段:object field

比如如下index中,address就是个对象字段(object类型)

PUT /company/employee/1
{
  "address": {
    "country": "china",
    "province": "guangdong",
    "city": "guangzhou"
  },
  "name": "jack",
  "age": 27,
  "join_date": "2017-01-01"
}

< END >

本文章收录于【Elasticsearch 系列】,将详细的讲解 Elasticsearch 整个大体系,包括但不限于ELK讲解、ES调优、海量数据处理等

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>