數據庫建表的時候,咱們的DDL語句通常都會指定每一個字段的存儲類型,例如:varchar,int,datetime等等,目的很明確,就是更精確的存儲數據,防止數據類型格式混亂。html
CREATE TABLE `shop_` ( `id_` varchar(36) NOT NULL COMMENT 'id', `shop_name_` varchar(50) DEFAULT NULL COMMENT '商品名稱', `shop_integral_` int(11) DEFAULT NULL COMMENT '兌換所需積分', `shop_money_` decimal(10,0) DEFAULT NULL COMMENT '劵面金額', `start_time_` datetime DEFAULT NULL COMMENT '有效開始時間', `end_time_` datetime DEFAULT NULL COMMENT '有效結束時間', `is_delete_` int(1) DEFAULT '1' COMMENT '是否刪除-1:有效,0:刪除', PRIMARY KEY (`id_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
在 Elasticsearch中也是這樣,建立索引的時候通常也須要指定索引的字段類型,這種方式成爲映射(Mapping)。sql
映射(Mapping)針對的是文檔的字段,數據庫中有varchar,int,datetime等數據類型,那麼咱們ElasticSearch中又有哪些字段類型,每一個字段類型都表明什麼意思呢?數據庫
ElasticSearch更新頻繁,如下內容是針對6.x版本的,對於5.x版本以及以前的版本可能有所不一樣,將來7.x版本也許也會有所改變,本篇不能作到面面俱到,因此你們能夠針對本身的版本查閱官方文檔。json
Elasticsearch支持文檔字段的多種不一樣數據類型,根據官方文檔的分類,能夠劃分爲如下幾個類別:
核心數據類型,複雜數據類型,Geo(地理)數據類型,專用數據類型和多字段。數組
這裏咱們重點介紹下 text 和 keyword 的區別:app
text 用於索引全文值的字段,例如電子郵件正文或產品說明。這些字段是analyzed,它們經過分詞器傳遞 ,以在被索引以前將字符串轉換爲單個術語的列表。分析過程容許Elasticsearch搜索單個單詞中 每一個完整的文本字段。文本字段不用於排序,不多用於聚合(儘管 重要的文本聚合 是一個值得注意的例外)。elasticsearch
keyword 用於索引結構化內容的字段,例如電子郵件地址,主機名,狀態代碼,郵政編碼或標籤。它們一般用於過濾,排序,和聚合。keyword字段只能按其確切值進行搜索。若是您須要索引電子郵件正文或產品說明等全文內容,則可能應該使用text字段。ide
有時候一個字段同時擁有全文類型(text)和關鍵字類型(keyword)是有用的:一個用於全文搜索,另外一個用於聚合和排序。這能夠經過多字段類型來實現。ui
有時候單純的一個字段類型知足不了咱們複雜的需求,爲了避免同的目的,以不一樣的方式索引同一個字段一般頗有用。多字段也是ES的一種數據類型,只不過結合了更多的功能。編碼
例如,對於字符串字段,咱們既能夠將它映射爲text類型用於全文搜索,亦能夠將它映射爲keyword類型用於排序或聚合,或者,還可使用標準分詞器、英語分詞器和其餘語言分詞器索引文本字段。
大多數數據類型都經過fields
參數支持多字段。例如對於城市名稱的多字段映射,能夠這樣寫:
PUT my_index { "mappings": { "_doc": { "properties": { "cityName": { "type": "text", "fields": { "raw": { "type": "keyword" } } } } } } }
Elasticsearch的字段類型講解完了,咱們接下來正式介紹 ES的映射,ES是如何將索引文檔和數據類型進行關聯的,建立索引前是否必須制定索引文檔的數據類型呢?
映射是定義一個文檔及其包含的字段如何存儲和索引的過程。例如,使用映射來定義:
其實在 ElasticSearch中能夠不須要事先定義映射(Mapping),文檔寫入ElasticSearch時,會根據文檔字段自動識別類型,可是經過這種自動識別的字段不是很精確,對於一些複雜的須要分詞的就不適合了。
根據是否自動識別映射類型,咱們能夠將映射分爲動態映射和靜態映射。
動態映射,即不事先指定映射類型(Mapping),文檔寫入ElasticSearch時,ES會根據文檔字段自動識別類型,這種機制稱之爲動態映射。
靜態映射,即人爲事先定義好映射,包含文檔的各個字段及其類型等,這種方式稱之爲靜態映射,亦可稱爲顯式映射。
Elasticsearch最重要的功能之一是它試圖擺脫你的方式,讓你儘快開始探索你的數據。Elasticsearch試圖讓你成功安裝環境以後就能夠直接使用。要索引文檔,您沒必要首先建立索引、定義映射類型和定義字段,其實您只需索引一個文檔數據,而後索引、類型和字段將自動生效。
索引一個圖書的文檔:
PUT /library/book/1 { "bookId":1, "bookName":"Java核心技術 卷I", "publishDate":"2014-03-12" }
返回結果以下,表示成功
{ "_index": "library", "_type": "book", "_id": "1", "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 0, "_primary_term": 1 }
咱們看下mapping映射信息
GET library/_mapping
獲得以下映射信息,重點關注mapping節點的內容
{ "library": { "mappings": { "book": { "properties": { "bookId": { "type": "long" }, "bookName": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "publishDate": { "type": "date" } } } } } }
能夠看到,咱們並無建立索引映射,Elasticsearch自動根據文檔數據爲咱們映射了字段類型,bookId的映射類型爲long,bookName的映射類型爲多字段的即爲text,同時也爲keyword,publishDate的映射類型爲date。能夠看到ES的動態映射功能仍是蠻強大的。
默認狀況下,當在文檔中找到之前未見過的字段時,Elasticsearch會自動將這個新字段添加到類型映射中。咱們能夠在文檔和object級別禁用這項功能,具體操做方式就是經過將dynamic
參數設置爲false
或strict
,設爲false是忽略新字段,而設爲strict是若是遇到未知字段,就拋出異常。
假設啓用了動態字段映射功能,則使用一些簡單的規則來肯定字段應具備的數據類型:
JSON datatype | Elasticsearch datatype |
---|---|
null | 沒有字段添加 |
true or false | boolean |
integer | long |
object | object |
array | 依賴於數組中首個非空值 |
string | 能夠是日期字段、double或long字段,也能夠是帶有關鍵字子字段的文本字段。 |
上面這些是能夠動態檢測到的字段數據類型,而其餘的之外的字段必需要顯式映射數據類型了。
對於string字符串字段,動態映射的結果會有多種,可能映射爲日期類型,也可能映射爲double或long類型,也可能映射爲帶有關鍵字的text類型,具體結果要看配置的檢測類型,是日期檢測仍是數字檢測。
日期檢測
若是date_detection
啓用(默認),則檢查新字符串字段以查看其內容是否與dynamic_date_formats
指定的任何日期模式匹配 。若是找到匹配項,那麼則添加爲具備對應格式的date新字段。
默認值爲
dynamic_date_formats:[ "strict_date_optional_time","yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"]
例如:
PUT my_index/_doc/1 { "create_date": "2015/09/02" }
經過GET my_index/_mapping
獲得的結果爲:
{ "my_index": { "mappings": { "_doc": { "properties": { "city": { "type": "text", "fields": { "raw": { "type": "keyword" } } }, "create_date": { "type": "date", "format": "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis" } } } } } }
動態日期檢測能夠經過設置date_detection
爲false
來禁用:
PUT my_index { "mappings": { "_doc": { "date_detection": false } } } PUT my_index/_doc/1 { "create": "2015/09/02" }
禁用以後,從新獲取映射類型,獲得以下結果:
{ "my_index": { "mappings": { "_doc": { "date_detection": false, "properties": { "create": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } } } }
這時,create_date字段已被添加爲文本字段。咱們也能夠自定義檢測到的日期格式,經過dynamic_date_formats
能夠自定義以支持您本身的日期格式:
PUT my_index { "mappings":{ "_ doc":{ "dynamic_date_formats":["MM / dd / yyyy"] } } }
數字檢測
雖然JSON支持本機浮點和整數數據類型,但某些應用程序或語言有時可能將數字呈現爲字符串。一般,正確的解決方案是顯式映射這些字段,但能夠啓用數字檢測(默認狀況下禁用)以自動執行此操做:
PUT my_index { "mappings":{ "_ doc":{ "numeric_detection":true } } } PUT my_index / _doc / 1 { "my_float":"1.0", "my_integer":"1" }
其中my_float字段將添加爲float字段,my_integer字段將添加爲long字段。
除了上面列出的選項外,還能夠進一步自定義動態字段映射規則dynamic_templates
,動態模板容許您定義可應用於動態添加字段的自定義映射,具體取決於:
更多具體內容可參考官方文檔,Dynamic templates一章這裏就很少敘述了。
動態映射的自動類型推測功能並非100%正確的,這就須要靜態映射機制。靜態映射與關係數據庫中建立表語句類型,須要事先指定字段類型。相對於動態映射,靜態映射能夠添加更加詳細字段類型、更精準的配置信息等。
既然能夠自定義映射字段類型,那麼那些複雜的字段類型和分詞器咱們均可以根據本身需求添加了,以提供了字段映射使用的各類映射參數的詳細說明,這些映射參數對於某些或全部字段數據類型是通用的,內容太多,這裏感興趣的讀者能夠點擊具體連接閱讀。
映射參數 | 說明 |
---|---|
analyzer | 分析器 |
normalizer | 在 Elasticsearch 中處理字符串類型的數據時,若是咱們想把整個字符串做爲一個完整的 term 存儲,咱們一般會將其類型 type 設定爲 keyword。但有時這種設定又會給咱們帶來麻煩,好比同一個數據再寫入時因爲沒有作好清洗,致使大小寫不一致,好比 apple、Apple兩個實際都是 apple,但當咱們去搜索 apple時卻沒法返回 Apple的文檔。要解決這個問題,就須要 Normalizer出場了。 |
boost | 單個字段能夠自動提高以計數更多的相關性得分 |
coerce | 強制嘗試清除髒值以適合字段的數據類型。數據並不老是乾淨的,根據它的生成方式,數字可能會在JSON正文中呈現爲真正的JSON數字,例如5,但它也可能呈現爲字符串,例如"5"。或者,應該是整數的數字能夠替代地呈現爲浮點,例如5.0,或甚至 "5.0"。 |
copy_to | copy_to參數容許您建立自定義 _all字段,能夠將多個字段的值複製到組字段中,而後能夠將其做爲單個字段進行查詢。 |
doc_values | |
dynamic | 設置動態映射 |
enabled | enabled設置只能應用於映射類型和 object字段,致使Elasticsearch徹底跳過對字段內容的解析 |
fielddata | |
eager_global_ordinals | |
format | 格式化日期 |
ignore_above | |
ignore_malformed | |
index_options | |
index | |
fields | |
norms | |
null_value | 當字段設置爲null,(或空數組或null值數組)時,它被視爲該字段沒有值。不能被索引或搜索 |
position_increment_gap | |
properties | |
search_analyzer | |
similarity | |
store | |
term_vector |