es的映射就相当于编程语言中给变量定义类型,定义后的变量使用起来更高效,未定义的变量相较于定义的性能肯定是不如的。所以需要掌握es映射。

未定义映射es会对提供的数据进行类型猜测,如果对自动判断的类型及参数设置不满意,或者需要使用一些更高级的映射设置,那么就需要使用自定义映射。

添加映射格式:

curl -XPUT http://localhost:9200/索引名称/类型名称/_mapping?pretty -d '
{
"properties":{
"字段名称":{
"type":"字段类型",
"store":"是否存储",
"index":"索引方式、是否分析"
...
}
}
}'

创建my_text3索引

PUT /my_text3
{
"mappings": {
"doc": { #类型
"properties": {
"name":{ #字段名
"type": "text" #字段类型
}
}
}
}
}

mapping中字段可查询官网:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html

一个索引对应一个映射,一个索引下多个type无法对应多个映射的。7.0版本以后,索引下的type类型就弃用了。最主要原因为了提高性能,具体原因参考官网和此文档链接

一、字段数据类型:

  • text,keyword,date,long,double,boolean,ip
  • 支持josn的分层特性类型:object,nested
  • 特殊类型: geo_point,geo_shape,completion

    更多类型参考官网文档:链接

常用类型:

  • text:文本类型,会对内容进行分词,如果不指定分词则使用默认的standard分词器,支持模糊查询。
  • keyword:关键字类型,不会对内容进行分词,只能按其精确值搜索。通常用于过滤、排序和聚合。
  • date:时间类型
  • long,integer:整型
  • double,float:符点数
  • ip :地址类型,搜索时可以位置搜索

为不同目的以不同方式索引相同字段通常很有用。例如,string可以将字段索引为全文搜索类型text和精确搜索类型keyword,以及用于排序或聚合的字段numeric

二、索引设置(settings):

用于控制与索引相关方面配置。如刷新间隔时间,主副分片数等

PUT /my_text3
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
}
}
  • number_of_shards :主分片数,默认为5,奇数。7.x版本后默认为1。这里使用单机做实验,只用一个主分片即可
  • number_of_replicas :副本分片,默认为1。当主分片丢失时,可用于数据恢复。这里是单机实验,无所谓副本分片。

查看索引settings:

GET /my_text3/_settings?pretty

更多的setting设置还请参考官网文档

动态更新setting链接

三、Meta-fields

特殊字段,在索引映射中统一以_下划线开头。

查询结果:

  "hits" : {
"total" : 1,
"max_score" : 0.5753642,
"hits" : [
{
"_index" : "my_text3",
"_type" : "doc",
"_id" : "3",
"_score" : 0.5753642,
"_source" : {
"name" : "Kobe Bryant",
"age" : 40
}
}
]
}
}

常见元字段:

  • _id : 唯一标识
  • _index : 索引名,即文档所在的索引
  • _score : 得分
  • _type : 文档的类型名
  • _uid : _type和_id连接一起构造成的复合主键
  • _source : 存储文档中所有字段的集合。默认为true,如果设置为false,那么你将只能指定获取字段搜索和结果。使用默认即可。你也可以尝试设置成false再query下试试。

默认情况下,_uid字段是被存储(可取回)和索引(可搜索)的。 _type字段被索引但是没有存储,_id_index字段则既没有被索引也没有被存储,这意味着它们并不是真实存在的。_source不被索引被存储。

更多字段参考官方文档

四、多重索引

多重索引只用于textkeyword类型。text字段用于搜索,不可用于排序,聚合等复杂操作。如果非要让text即可搜索也可进行高级操作,带来的代价通常是性能快速下降。所以建议给一个常用的字段定义两种类型,搜索时使用text,高级操作时使用keyword

PUT /my_text5
{
"mappings": {
"doc": {
"properties": {
"name":{
"type": "text",
"norms":false,
"fields": {
"raw": { #后缀,会额外生成name.raw的字段,类型为keyword
"type":"keyword",
"ignore_above":20
}
}
}
}
}
}
} ###插入数据
POST /my_text5/doc/1
{
"name":"walter dai"
} ###查询数据
GET /my_text5/_search
{
"query": {
"term": {
"name.raw": "walter dai" #查询name.raw也可以查询到数据
}
}
}

索引中未定义映射的字段,会默认映射成field(text类型)和field.keyword(keyword类型)两种。如果大多数场景用精确查找,可以反过来定义

"name": {
"type": "keyword",
"fields": {
"text": { "type": "text" }
}
}

官方文档

五、自定义映射

示例

PUT /my_text4
{
"mappings": {
"properties": {
"name":{
"type": "text",
"index": true,
"norms": false,
"analyzer": "standard",
"search_analyzer": "standard"
},
"age":{
"type": "integer"
},
"gender":{
"type": "boolean"
},
"country": {
"type": "keyword",
"ignore_above": 40
}
}
}
}
  • mappings : 映射
  • doc : _type默认类型。 链接
  • properties :类型映射,object字段和nested字段,并明确定义。默认object
  • name : 索引中的字段名称,下面括号中就是单独给每个字段配置属性
  • type :type设置字段类型,text为字符型,6.x废弃string类型了,integer整形,boolean布尔型true或false,keyword关键字等。链接
  • analyzer,search_analyzer :analyzer存储时的分析器,存储数据时,根据什么分析器来分析数据并倒排索引数据。search_analyzer是搜索时以什么分析器分析搜索数据并去查询匹配相应数据。存储和搜索时的分析器得一致,否则搜索的结果可能不是想要的。
  • index : 区分三种,完全为了性能。
index:analyzedtype:text,index:true分析字符串 ,全文索引。设置为text后,默认为true
index:not_analyzedtype:keyword精确搜索,不分析
index:noindex:false不索引,不可被搜索
  • analyzer:插入时分析器,text类型插入时,先分析,在建立倒排索引。
  • search_analyzer :搜索时分析器,搜索时先分析输入数据,并根据评分排序搜索到的数据。
  • ignore_above : 超过的字符将不被索引或存储,限定大小
  • norms : 默认为true,作用是当计算得分时,是否把字段长度用作参数计算。如果此字段仅用于聚合或者过滤,你应该设置为false。以减少磁盘开销

此处简单列举了些个人常用的配置,详细的配置还请参数官方文档。

六、动态映射

在使用之前不需要定义字段和映射类型,适合刚入门elk时使用,索引以logstash-开头就会默认使用动态映射。(程序自带的模版映射)

动态映射只适用于对数据不了解的情况下使用,否则为了数据的压缩和性能,我们都应该尽量不使用动态映射,除非像nginx request中带有很多个参数,需要将参数抽取出来时,就需要使用动态映射了。请求中的参数过多而无法一一列举出来。

可动态识别 datebooleanfloatlongobjectarraystring(string分为text和keyword)

不可以动态识别的类型,如ip:

PUT /my_text1/doc/10     #试先没有创建,my_text1的映射,直接PUT数据
{
"ipp": "192.168.10.3"
} GET /my_text1/_mapping #查看映射
{
"my_text1" : {
"mappings" : {
"doc" : {
"properties" : { #默认的双引号内的数据为text和keyword类型
"ipp" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
...

正常情况下,当你自定义映射时,就应该考虑到每个字段的类型,是否需要索引,聚合等一系列后续操作。如果有没法定义的类型数据时,才需要使用dynamic配置项,否则你应该或尽可能给每一个数据类型定义好。

dynamic支持三种选项:

  • true : 默认值,当有未定义的字段插入时,elastic动态判断类型,无论判断是否成功。都将字段添加到映射中。
  • flase :未定义的字段插入时,将会被忽略,不被索引。但是会存储至_source字段里
  • strict :未定义字段插入时,抛出异常并拒绝文档。

示例:将所有未定义的字段只映射为keyword类型

PUT /my_text6
{
"mappings": {
"doc": {
"dynamic_templates":[ #方括号内是定义动态映射规则
{
"message_field":{ #名称
"match":"*", #匹配哪些字段,*表示所有未定义的字段。还可以用 match_pattern的正则匹配,glob匹配规则,umatch不匹配某些字段等等
"mapping":{ #映射成什么类型
"type":"keyword",
"ignore_above":256
}
}
}
],
"properties":{ #明确定义字段映射
"name":{
"type":"text",
"norms":false
}
}
}
}
}

更多配置参数请参考官网

七、修改映射

mapping中已经定义的字段类型,一旦创建,不能修改,不能删除,只可以新增字段。

PUT /my_text3/doc/_mapping     #使用_mapping接口新增字段映射
{
"properties": {
"age": { #之前索引中没有的字段
"type": "integer"
}
}
}

如果需要修改字段映射,则需要使用reindex功能。还请参考另外博文

八、索引模版

前面内容中的动态模版是针对字段进行动态匹配。现在有这样一种情况,同一类型的nginx日志,但是存储进es时会有很多索引,这时我们要为每一个索引都先PUT一个映射,然后才能存储数据。这时为了方便同一类型的索引,就可以使用索引模版,定义一个 n-开头的索引名都引用同一个映射。

模版映射API:

GET /_cat/templates
GET /_cat/templates?name=xxx #查询某个模版
DELETE /_template/xxx #删除模版

我的nginx模版:

curl -XPUT "http://node2003:9200/_template/nginx" -H 'Content-Type: application/json' -d'
{
"order": 10, #优先级,值越大,优先级越高。默认为0
"index_patterns": "n-*", #匹配索引的格式,只要匹配上都使用此模版映射
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"doc":{
"properties": {
"@timestamp": {
"type": "date"
},
"agent": {
"type": "keyword",
"ignore_above": 256
},
"city_domain_name":{
"type":"keyword",
"ignore_above":256
},
"android_version": {
"type": "keyword"
},
"ios_version": {
"type": "keyword"
},
"body_bytes_sent": {
"type": "integer"
},
"http_referer": {
"type": "text",
"norms": false,
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"http_x_forwarded_for": {
"type": "keyword"
},
"httpversion": {
"type": "keyword",
"index": false
}, "remote_addr": {
"type": "ip"
},
"request": {
"type": "text",
"norms": false,
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"request_body": {
"type": "text",
"norms": false
},
"request_method": {
"type": "keyword",
"ignore_above": 10
},
"request_time": {
"type": "float"
},
"scheme": {
"type": "keyword",
"ignore_above": 20
},
"status": {
"type": "integer"
},
"upstream_addr": {
"type": "keyword"
},
"upstream_cache_status": {
"type": "keyword"
},
"upstream_response_time": {
"type": "float"
}
}
}
}
}'

总结:

mapping映射是非常重要。个人总结如有错误,还望指正。

官方链接:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html

05-26 12:10