@[toc]
ElasticSearch 系列教程咱們前面已經連着發了三篇了,今天第四篇,咱們來聊一聊 Es 中的動態映射、靜態映射以及四種不一樣的字段類型。java
本文是鬆哥所錄視頻教程的一個筆記,筆記簡明扼要,完整內容小夥伴們能夠參考視頻,視頻下載連接:https://pan.baidu.com/s/1oKiV... 提取碼: p3sxgit
映射就是 Mapping,它用來定義一個文檔以及文檔所包含的字段該如何被存儲和索引。因此,它其實有點相似於關係型數據庫中表的定義。github
動態映射數據庫
顧名思義,就是自動建立出來的映射。es 根據存入的文檔,自動分析出來文檔中字段的類型以及存儲方式,這種就是動態映射。數組
舉一個簡單例子,新建一個索引,而後查看索引信息:app
在建立好的索引信息中,能夠看到,mappings 爲空,這個 mappings 中保存的就是映射信息。性能
如今咱們向索引中添加一個文檔,以下:編碼
PUT blog/_doc/1 { "title":"1111", "date":"2020-11-11" }
文檔添加成功後,就會自動生成 Mappings:es5
能夠看到,date 字段的類型爲 date,title 的類型有兩個,text 和 keyword。spa
默認狀況下,文檔中若是新增了字段,mappings 中也會自動新增進來。
有的時候,若是但願新增字段時,可以拋出異常來提醒開發者,這個能夠經過 mappings 中 dynamic 屬性來配置。
dynamic 屬性有三種取值:
具體配置方式以下,建立索引時指定 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 } }
此時日期類型就回當成文原本處理。
靜態映射
略。
es 中動態映射類型推斷方式以下:
JSON 中的數據 | 自動推斷出來的數據類型 |
---|---|
null | 沒有字段被添加 |
true/false | boolean |
浮點數字 | float |
數字 | long |
JSON 對象 | object |
數組 | 數組中的第一個非空值來決定 |
string | text/keyword/date/double/long 都有可能 |
類型 | 取值範圍 |
---|---|
long | -2^63到2^63-1 |
integer | -2^31到2^31-1 |
short | -2^15到2^15-1 |
byte | -2^7到2^7-1 |
double | 64 位的雙精度 IEEE754 浮點類型 |
float | 32 位的雙精度 IEEE754 浮點類型 |
half_float | 16 位的雙精度 IEEE754 浮點類型 |
scaled_float | 縮放類型的浮點類型 |
scaled_float 舉例:
PUT product { "mappings": { "properties": { "name":{ "type": "text" }, "price":{ "type": "scaled_float", "scaling_factor": 100 } } } }
因爲 JSON 中沒有日期類型,因此 es 中的日期類型形式就比較多樣:
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" }
上面三個文檔中的日期均可以被解析,內部存儲的是毫秒計時的長整型數。
JSON 中的 「true」、「false」、true、false 均可以。
二進制接受的是 base64 編碼的字符串,默認不存儲,也不可搜索。
定義的時候,指定範圍類型便可:
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。
es 中沒有專門的數組類型。默認狀況下,任何字段均可以有一個或者多個值。須要注意的是,數組中的元素必須是同一種類型。
添加數組是,數組中的第一個元素決定了整個數組的類型。
因爲 JSON 自己具備層級關係,因此文檔包含內部對象。內部對象中,還能夠再包含內部對象。
PUT product/_doc/2 { "date":"2020-11-11T11:11:11Z", "ext_info":{ "address":"China" } }
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" } }
優勢
文檔存儲在一塊兒,讀取性能高。
缺點
更新父或者子文檔時須要更新更個文檔。
使用場景:
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/#/
GeoJSON | ElasticSearch | 備註 |
---|---|---|
Point | point | 一個由經緯度描述的點 |
LineString | linestring | 一個任意的線條,由兩個以上的點組成 |
Polygon | polygon | 一個封閉多邊形 |
MultiPoint | multipoint | 一組不連續的點 |
MultiLineString | multilinestring | 多條不關聯的線 |
MultiPolygon | multipolygon | 多個多邊形 |
GeometryCollection | geometrycollection | 幾何對象的集合 |
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]] } }
存儲 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" } } }
用於統計字符串分詞後的詞項個數。
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+ 個項目需求文檔,想作個項目練練手的小夥伴不妨看看哦~