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
不被索引被存储。
更多字段参考官方文档
四、多重索引
多重索引只用于text
和keyword
类型。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中带有很多个参数,需要将参数抽取出来时,就需要使用动态映射了。请求中的参数过多而无法一一列举出来。
可动态识别 date
、boolean
、float
、long
、object
、array
和string
(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