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