mapping 映射

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 : 区分三种,完全为了性能。
5.x前 5.x后 意思
index:analyzed type:text,index:true 分析字符串 ,全文索引。设置为text后,默认为true
index:not_analyzed type:keyword 精确搜索,不分析
index:no index:false 不索引,不可被搜索
  • analyzer:插入时分析器,text类型插入时,先分析,在建立倒排索引。
  • search_analyzer :搜索时分析器,搜索时先分析输入数据,并根据评分排序搜索到的数据。

    elastic自带standard,whitesapce,english,simple分析器。如在配置映射时不指定分析器,则默认使用standard分析器。一般analyzer和search_analyzer得一致,不然搜索就可能会得不到想要的结果。中文可使用ik分词器。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

猜你喜欢

转载自www.cnblogs.com/dance-walter/p/10684923.html