說在前面: Elasticsearch中每一個field都要精確對應一個數據類型.
本文的全部演示, 都是基於Elasticsearch 6.6.10進行的, 不一樣的版本可能存在API發生修改、不支持的狀況, 還請注意.git
(1) 使用示例:web
PUT website { "mappings": { "blog": { "properties": { "title": {"type": "string"}, // 全文本 "tags": {"type": "string", "index": "not_analyzed"} // 關鍵字, 不分詞 } } } }
(2) ES 5.6.10中的響應信息:json
#! Deprecation: The [string] field is deprecated, please use [text] or [keyword] instead on [tags] #! Deprecation: The [string] field is deprecated, please use [text] or [keyword] instead on [title] { "acknowledged": true, "shards_acknowledged": true, "index": "website" }
(3) ES 6.6.10中的響應信息:數組
{ "error": { "root_cause": [ { "type": "mapper_parsing_exception", "reason": "No handler for type [string] declared on field [title]" } ], "type": "mapper_parsing_exception", "reason": "Failed to parse mapping [blog]: No handler for type [string] declared on field [title]", "caused_by": { "type": "mapper_parsing_exception", "reason": "No handler for type [string] declared on field [title]" } }, "status": 400 }
可知string類型的field已經被移除了, 咱們須要用text或keyword類型來代替string.bash
在Elasticsearch 5.4 版本開始, text取代了須要分詞的string.app
—— 當一個字段須要用於全文搜索(會被分詞), 好比產品名稱、產品描述信息, 就應該使用text類型.elasticsearch
text的內容會被分詞, 能夠設置是否須要存儲:
"index": "true|false"
.
text類型的字段不能用於排序, 也不多用於聚合.ide
使用示例:ui
PUT website { "mappings": { "blog": { "properties": { "summary": {"type": "text", "index": "true"} } } } }
在Elasticsearch 5.4 版本開始, keyword取代了不須要分詞的string.
—— 當一個字段須要按照精確值進行過濾、排序、聚合等操做時, 就應該使用keyword類型.
keyword的內容不會被分詞, 能夠設置是否須要存儲:
"index": "true|false"
.
使用示例:
PUT website { "mappings": { "blog": { "properties": { "tags": {"type": "keyword", "index": "true"} } } } }
數字類型有以下分類:
類型 | 說明 |
---|---|
byte | 有符號的8位整數, 範圍: [-128 ~ 127] |
short | 有符號的16位整數, 範圍: [-32768 ~ 32767] |
integer | 有符號的32位整數, 範圍: [$-2^{31}$ ~ $2^{31}$-1] |
long | 有符號的32位整數, 範圍: [$-2^{63}$ ~ $2^{63}$-1] |
float | 32位單精度浮點數 |
double | 64位雙精度浮點數 |
half_float | 16位半精度IEEE 754浮點類型 |
scaled_float | 縮放類型的的浮點數, 好比price字段只需精確到分, 57.34縮放因子爲100, 存儲結果爲5734 |
使用注意事項:
儘量選擇範圍小的數據類型, 字段的長度越短, 索引和搜索的效率越高;
優先考慮使用帶縮放因子的浮點類型.
使用示例:
PUT shop { "mappings": { "book": { "properties": { "name": {"type": "text"}, "quantity": {"type": "integer"}, // integer類型 "price": { "type": "scaled_float", // scaled_float類型 "scaling_factor": 100 } } } } }
JSON沒有日期數據類型, 因此在ES中, 日期能夠是:
若是時區未指定, 日期將被轉換爲UTC格式, 但存儲的倒是長整型的毫秒值.
能夠自定義日期格式, 若未指定, 則使用默認格式:strict_date_optional_time||epoch_millis
(1) 使用日期格式示例:
// 添加映射 PUT website { "mappings": { "blog": { "properties": { "pub_date": {"type": "date"} // 日期類型 } } } } // 添加數據 PUT website/blog/11 { "pub_date": "2018-10-10" } PUT website/blog/12 { "pub_date": "2018-10-10T12:00:00Z" } // Solr中默認使用的日期格式 PUT website/blog/13 { "pub_date": "1589584930103" } // 時間的毫秒值
(2) 多種日期格式:
多個格式使用雙豎線
||
分隔, 每一個格式都會被依次嘗試, 直到找到匹配的.
第一個格式用於將時間毫秒值轉換爲對應格式的字符串.
使用示例:
// 添加映射 PUT website { "mappings": { "blog": { "properties": { "date": { "type": "date", // 能夠接受以下類型的格式 "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" } } } } }
能夠接受表示真、假的字符串或數字:
二進制類型是Base64編碼字符串的二進制值, 不以默認的方式存儲, 且不能被搜索.
使用示例:
// 添加映射 PUT website { "mappings": { "blog": { "properties": { "blob": {"type": "binary"} // 二進制 } } } } // 添加數據 PUT website/blog/1 { "title": "Some binary blog", "blob": "hED903KSrA084fRiD5JLgY==" }
注意: Base64編碼的二進制值不能嵌入換行符
\n
.
range類型支持如下幾種:
類型 | 範圍 |
---|---|
integer_range | $-2^{31}$ ~ $2^{31}-1$ |
long_range | $-2^{63}$ ~ $2^{63}-1$ |
float_range | 32位單精度浮點型 |
double_range | 64位雙精度浮點型 |
date_range | 64位整數, 毫秒計時 |
ip_range | IP值的範圍, 支持IPV4和IPV6, 或者這兩種同時存在 |
(1) 添加映射:
PUT company { "mappings": { "department": { "properties": { "expected_number": { // 預期員工數 "type": "integer_range" }, "time_frame": { // 發展時間線 "type": "date_range", "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" }, "ip_whitelist": { // ip白名單 "type": "ip_range" } } } } }
(2) 添加數據:
PUT company/department/1 { "expected_number" : { "gte" : 10, "lte" : 20 }, "time_frame" : { "gte" : "2018-10-01 12:00:00", "lte" : "2018-11-01" }, "ip_whitelist": "192.168.0.0/16" }
(3) 查詢數據:
GET company/department/_search { "query": { "term": { "expected_number": { "value": 12 } } } } GET company/department/_search { "query": { "range": { "time_frame": { "gte": "208-08-01", "lte": "2018-12-01", "relation": "within" } } } }
查詢結果:
{ "took": 26, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 1.0, "hits": [ { "_index": "company", "_type": "department", "_id": "1", "_score": 1.0, "_source": { "expected_number": { "gte": 10, "lte": 20 }, "time_frame": { "gte": "2018-10-01 12:00:00", "lte": "2018-11-01" }, "ip_whitelist" : "192.168.0.0/16" } } ] } }
ES中沒有專門的數組類型, 直接使用[]定義便可;
數組中全部的值必須是同一種數據類型, 不支持混合數據類型的數組:
① 字符串數組: ["one", "two"];
② 整數數組: [1, 2];
③ 由數組組成的數組: [1, [2, 3]], 等價於[1, 2, 3];
④ 對象數組: [{"name": "Tom", "age": 20}, {"name": "Jerry", "age": 18}].
注意:
- 動態添加數據時, 數組中第一個值的類型決定整個數組的類型;
- 不支持混合數組類型, 好比[1, "abc"];
- 數組能夠包含null值, 空數組[]會被當作missing field —— 沒有值的字段.
JSON文檔是分層的: 文檔能夠包含內部對象, 內部對象也能夠包含內部對象.
(1) 添加示例:
PUT employee/developer/1 { "name": "ma_shoufeng", "address": { "region": "China", "location": {"province": "GuangDong", "city": "GuangZhou"} } }
(2) 存儲方式:
{ "name": "ma_shoufeng", "address.region": "China", "address.location.province": "GuangDong", "address.location.city": "GuangZhou" }
(3) 文檔的映射結構相似爲:
PUT employee { "mappings": { "developer": { "properties": { "name": { "type": "text", "index": "true" }, "address": { "properties": { "region": { "type": "keyword", "index": "true" }, "location": { "properties": { "province": { "type": "keyword", "index": "true" }, "city": { "type": "keyword", "index": "true" } } } } } } } } }
嵌套類型是對象數據類型的一個特例, 可讓array類型的對象被獨立索引和搜索.
① 添加數據:
PUT game_of_thrones/role/1 { "group": "stark", "performer": [ {"first": "John", "last": "Snow"}, {"first": "Sansa", "last": "Stark"} ] }
② 內部存儲結構:
{ "group": "stark", "performer.first": [ "john", "sansa" ], "performer.last": [ "snow", "stark" ] }
③ 存儲分析:
能夠看出, user.first和user.last會被平鋪爲多值字段, 這樣一來, John和Snow之間的關聯性就丟失了.
在查詢時, 可能出現John Stark的結果.
若是須要對以最對象進行索引, 且保留數組中每一個對象的獨立性, 就應該使用嵌套數據類型.
—— 嵌套對象實質是將每一個對象分離出來, 做爲隱藏文檔進行索引.
① 建立映射:
PUT game_of_thrones { "mappings": { "role": { "properties": { "performer": {"type": "nested" } } } } }
② 添加數據:
PUT game_of_thrones/role/1 { "group" : "stark", "performer" : [ {"first": "John", "last": "Snow"}, {"first": "Sansa", "last": "Stark"} ] }
③ 檢索數據:
GET game_of_thrones/_search { "query": { "nested": { "path": "performer", "query": { "bool": { "must": [ { "match": { "performer.first": "John" }}, { "match": { "performer.last": "Snow" }} ] } }, "inner_hits": { "highlight": { "fields": {"performer.first": {}} } } } } }
地理點類型用於存儲地理位置的經緯度對, 可用於:
- 查找必定範圍內的地理點;
- 經過地理位置或相對某個中心點的距離聚合文檔;
- 將距離整合到文檔的相關性評分中;
- 經過距離對文檔進行排序.
(1) 添加映射:
PUT employee { "mappings": { "developer": { "properties": { "location": {"type": "geo_point"} } } } }
(2) 存儲地理位置:
// 方式一: 緯度 + 經度鍵值對 PUT employee/developer/1 { "text": "小蠻腰-鍵值對地理點參數", "location": { "lat": 23.11, "lon": 113.33 // 緯度: latitude, 經度: longitude } } // 方式二: "緯度, 經度"的字符串參數 PUT employee/developer/2 { "text": "小蠻腰-字符串地理點參數", "location": "23.11, 113.33" // 緯度, 經度 } // 方式三: ["經度, 緯度"] 數組地理點參數 PUT employee/developer/3 { "text": "小蠻腰-數組參數", "location": [ 113.33, 23.11 ] // 經度, 緯度 }
(3) 查詢示例:
GET employee/_search { "query": { "geo_bounding_box": { "location": { "top_left": { "lat": 24, "lon": 113 }, // 地理盒子模型的上-左邊 "bottom_right": { "lat": 22, "lon": 114 } // 地理盒子模型的下-右邊 } } } }
是多邊形的複雜形狀. 使用較少, 這裏省略.
能夠參考這篇文章: Elasticsearch地理位置總結
IP類型的字段用於存儲IPv4或IPv6的地址, 本質上是一個長整型字段.
(1) 添加映射:
PUT employee { "mappings": { "customer": { "properties": { "ip_addr": { "type": "ip" } } } } }
(2) 添加數據:
PUT employee/customer/1 { "ip_addr": "192.168.1.1" }
(3) 查詢數據:
GET employee/customer/_search { "query": { "term": { "ip_addr": "192.168.0.0/16" } } }
token_count類型用於統計字符串中的單詞數量.
本質上是一個整數型字段, 接受並分析字符串值, 而後索引字符串中單詞的個數.
(1) 添加映射:
PUT employee { "mappings": { "customer": { "properties": { "name": { "type": "text", "fields": { "length": { "type": "token_count", "analyzer": "standard" } } } } } } }
(2) 添加數據:
PUT employee/customer/1 { "name": "John Snow" } PUT employee/customer/2 { "name": "Tyrion Lannister" }
(3) 查詢數據:
GET employee/customer/_search { "query": { "term": { "name.length": 2 } } }
參考資料
版權聲明
做者: 馬瘦風
出處: 博客園 馬瘦風的博客
您的支持是對博主的極大鼓勵, 感謝您的閱讀.
本文版權歸博主全部, 歡迎轉載, 但請保留此段聲明, 並在文章頁面明顯位置給出原文連接, 不然博主保留追究相關人員法律責任的權利.