@[toc]
ElasticSearch 系列教程咱们后面曾经连着发了三篇了,明天第四篇,咱们来聊一聊 Es 中的动静映射、动态映射以及四种不同的字段类型。

本文是松哥所录视频教程的一个笔记,笔记简明扼要,残缺内容小伙伴们能够参考视频,视频下载链接:https://pan.baidu.com/s/1oKiV... 提取码: p3sx

1.ElasticSearch 映射

映射就是 Mapping,它用来定义一个文档以及文档所蕴含的字段该如何被存储和索引。所以,它其实有点相似于关系型数据库中表的定义。

1.1 映射分类

动静映射

顾名思义,就是主动创立进去的映射。es 依据存入的文档,主动剖析进去文档中字段的类型以及存储形式,这种就是动静映射。

举一个简略例子,新建一个索引,而后查看索引信息:

在创立好的索引信息中,能够看到,mappings 为空,这个 mappings 中保留的就是映射信息。

当初咱们向索引中增加一个文档,如下:

PUT blog/_doc/1{  "title":"1111",  "date":"2020-11-11"}

文档增加胜利后,就会主动生成 Mappings:

能够看到,date 字段的类型为 date,title 的类型有两个,text 和 keyword。

默认状况下,文档中如果新增了字段,mappings 中也会主动新增进来。

有的时候,如果心愿新增字段时,可能抛出异样来揭示开发者,这个能够通过 mappings 中 dynamic 属性来配置。

dynamic 属性有三种取值:

  • true,默认即此。主动增加新字段。
  • false,疏忽新字段。
  • strict,严格模式,发现新字段会抛出异样。

具体配置形式如下,创立索引时指定 mappings(这其实就是动态映射):

PUT blog{  "mappings": {    "dynamic":"strict",    "properties": {      "title":{        "type": "text"      },      "age":{        "type":"long"      }    }  }}

而后向 blog 中索引中增加数据:

PUT blog/_doc/2{  "title":"1111",  "date":"2020-11-11",  "age":99}

在增加的文档中,多出了一个 date 字段,而该字段没有预约义,所以这个增加操作就回报错:

{  "error" : {    "root_cause" : [      {        "type" : "strict_dynamic_mapping_exception",        "reason" : "mapping set to strict, dynamic introduction of [date] within [_doc] is not allowed"      }    ],    "type" : "strict_dynamic_mapping_exception",    "reason" : "mapping set to strict, dynamic introduction of [date] within [_doc] is not allowed"  },  "status" : 400}

动静映射还有一个日期检测的问题。

例如新建一个索引,而后增加一个含有日期的文档,如下:

PUT blog/_doc/1{  "remark":"2020-11-11"}

增加胜利后,remark 字段会被推断是一个日期类型。

此时,remark 字段就无奈存储其余类型了。

PUT blog/_doc/1{  "remark":"javaboy"}

此时报错如下:

{  "error" : {    "root_cause" : [      {        "type" : "mapper_parsing_exception",        "reason" : "failed to parse field [remark] of type [date] in document with id '1'. Preview of field's value: 'javaboy'"      }    ],    "type" : "mapper_parsing_exception",    "reason" : "failed to parse field [remark] of type [date] in document with id '1'. Preview of field's value: 'javaboy'",    "caused_by" : {      "type" : "illegal_argument_exception",      "reason" : "failed to parse date field [javaboy] with format [strict_date_optional_time||epoch_millis]",      "caused_by" : {        "type" : "date_time_parse_exception",        "reason" : "Failed to parse with all enclosed parsers"      }    }  },  "status" : 400}

要解决这个问题,能够应用动态映射,即在索引定义时,将 remark 指定为 text 类型。也能够敞开日期检测。

PUT blog{  "mappings": {    "date_detection": false  }}

此时日期类型就回当成文原本解决。

动态映射

略。

1.2 类型推断

es 中动静映射类型推断形式如下:

JSON 中的数据主动推断进去的数据类型
null没有字段被增加
true/falseboolean
浮点数字float
数字long
JSON 对象object
数组数组中的第一个非空值来决定
stringtext/keyword/date/double/long 都有可能

2.ElasticSearch 字段类型

2.1 外围类型

2.1.1 字符串类型

  • string:这是一个曾经过期的字符串类型。在 es5 之前,用这个来形容字符串,当初的话,它曾经被 text 和 keyword 代替了。
  • text:如果一个字段是要被全文检索的,比如说博客内容、新闻内容、产品描述,那么能够应用 text。用了 text 之后,字段内容会被剖析,在生成倒排索引之前,字符串会被分词器分成一个个词项。text 类型的字段不用于排序,很少用于聚合。这种字符串也被称为 analyzed 字段。
  • keyword:这种类型实用于结构化的字段,例如标签、email 地址、手机号码等等,这种类型的字段能够用作过滤、排序、聚合等。这种字符串也称之为 not-analyzed 字段。

2.1.2 数字类型

类型取值范畴
long-2^63到2^63-1
integer-2^31到2^31-1
short-2^15到2^15-1
byte-2^7到2^7-1
double64 位的双精度 IEEE754 浮点类型
float32 位的双精度 IEEE754 浮点类型
half_float16 位的双精度 IEEE754 浮点类型
scaled_float缩放类型的浮点类型
  • 在满足需要的状况下,优先应用范畴小的字段。字段长度越短,索引和搜寻的效率越高。
  • 浮点数,优先思考应用 scaled_float。

scaled_float 举例:

PUT product{  "mappings": {    "properties": {      "name":{        "type": "text"      },      "price":{        "type": "scaled_float",        "scaling_factor": 100      }    }  }}

2.1.3 日期类型

因为 JSON 中没有日期类型,所以 es 中的日期类型模式就比拟多样:

  • 2020-11-11 或者 2020-11-11 11:11:11
  • 一个从 1970.1.1 零点到当初的一个秒数或者毫秒数。

es 外部将工夫转为 UTC,而后将工夫依照 millseconds-since-the-epoch 的长整型来存储。

自定义日期类型:

PUT product{  "mappings": {    "properties": {      "date":{        "type": "date"      }    }  }}

这个可能解析进去的工夫格局比拟多。

PUT product/_doc/1{  "date":"2020-11-11"}PUT product/_doc/2{  "date":"2020-11-11T11:11:11Z"}PUT product/_doc/3{  "date":"1604672099958"}

下面三个文档中的日期都能够被解析,外部存储的是毫秒计时的长整型数。

2.1.4 布尔类型(boolean)

JSON 中的 “true”、“false”、true、false 都能够。

2.1.5 二进制类型(binary)

二进制承受的是 base64 编码的字符串,默认不存储,也不可搜寻。

2.1.6 范畴类型

  • integer_range
  • float_range
  • long_range
  • double_range
  • date_range
  • ip_range

定义的时候,指定范畴类型即可:

PUT product{  "mappings": {    "properties": {      "date":{        "type": "date"      },      "price":{        "type":"float_range"      }    }  }}

插入文档的时候,须要指定范畴的界线:

PUT product{  "mappings": {    "properties": {      "date":{        "type": "date"      },      "price":{        "type":"float_range"      }    }  }}

指定范畴的时,能够应用 gt、gte、lt、lte。

2.2 复合类型

2.2.1 数组类型

es 中没有专门的数组类型。默认状况下,任何字段都能够有一个或者多个值。须要留神的是,数组中的元素必须是同一种类型。

增加数组是,数组中的第一个元素决定了整个数组的类型。

2.2.2 对象类型(object)

因为 JSON 自身具备层级关系,所以文档蕴含外部对象。外部对象中,还能够再蕴含外部对象。

PUT product/_doc/2{  "date":"2020-11-11T11:11:11Z",  "ext_info":{    "address":"China"  }}

2.2.3 嵌套类型(nested)

nested 是 object 中的一个特例。

如果应用 object 类型,如果有如下一个文档:

{  "user":[    {      "first":"Zhang",      "last":"san"    },    {      "first":"Li",      "last":"si"    }    ]}

因为 Lucene 没有外部对象的概念,所以 es 会将对象档次扁平化,将一个对象转为字段名和值形成的简略列表。即下面的文档,最终存储模式如下:

{"user.first":["Zhang","Li"],"user.last":["san","si"]}

扁平化之后,用户名之间的关系没了。这样会导致如果搜寻 Zhang si 这个人,会搜寻到。

此时能够 nested 类型来解决问题,nested 对象类型能够放弃数组中每个对象的独立性。nested 类型将数组中的每一饿对象作为独立暗藏文档来索引,这样每一个嵌套对象都能够独立被索引。

{{"user.first":"Zhang","user.last":"san"},{"user.first":"Li","user.last":"si"}}

长处

文档存储在一起,读取性能高。

毛病

更新父或者子文档时须要更新更个文档。

2.3 天文类型

应用场景:

  • 查找某一个范畴内的地理位置
  • 通过地理位置或者绝对中心点的间隔来聚合文档
  • 把间隔整个到文档的评分中
  • 通过间隔对文档进行排序

2.3.1 geo_point

geo_point 就是一个坐标点,定义形式如下:

PUT people{  "mappings": {    "properties": {      "location":{        "type": "geo_point"      }    }  }}

创立时指定字段类型,存储的时候,有四种形式:

PUT people/_doc/1{  "location":{    "lat": 34.27,    "lon": 108.94  }}PUT people/_doc/2{  "location":"34.27,108.94"}PUT people/_doc/3{  "location":"uzbrgzfxuzup"}PUT people/_doc/4{  "location":[108.94,34.27]}

留神,应用数组形容,先经度后纬度。

地址地位转 geo_hash:http://www.csxgame.top/#/

2.3.2 geo_shape

GeoJSONElasticSearch备注
Pointpoint一个由经纬度形容的点
LineStringlinestring一个任意的线条,由两个以上的点组成
Polygonpolygon一个关闭多边形
MultiPointmultipoint一组不间断的点
MultiLineStringmultilinestring多条不关联的线
MultiPolygonmultipolygon多个多边形
GeometryCollectiongeometrycollection几何对象的汇合
circle一个圆形
envelope通过左上角和右下角两个点确定的矩形

指定 geo_shape 类型:

PUT people{  "mappings": {    "properties": {      "location":{        "type": "geo_shape"      }    }  }}

增加文档时须要指定具体的类型:

PUT people/_doc/1{  "location":{    "type":"point",    "coordinates": [108.94,34.27]  }}

如果是 linestring,如下:

PUT people/_doc/2{  "location":{    "type":"linestring",    "coordinates": [[108.94,34.27],[100,33]]  }}

2.4 非凡类型

2.4.1 IP

存储 IP 地址,类型是 ip:

PUT blog{  "mappings": {    "properties": {      "address":{        "type": "ip"      }    }  }}

增加文档:

PUT blog/_doc/1{  "address":"192.168.91.1"}

搜寻文档:

GET blog/_search{  "query": {    "term": {      "address": "192.168.0.0/16"    }  }}

2.4.2 token_count

用于统计字符串分词后的词项个数。

PUT blog{  "mappings": {    "properties": {      "title":{        "type": "text",        "fields": {          "length":{            "type":"token_count",            "analyzer":"standard"          }        }      }    }  }}

相当于新增了 title.length 字段用来统计分词后词项的个数。

增加文档:

PUT blog/_doc/1{  "title":"zhang san"}

能够通过 token_count 去查问:

GET blog/_search{  "query": {    "term": {      "title.length": 2    }  }}

最初,松哥还收集了 50+ 个我的项目需要文档,想做个我的项目练练手的小伙伴无妨看看哦~



需要文档地址:https://github.com/lenve/javadoc