字段類型詳解
字符串: text, keyword
5.0以後,string類型有重大變更,移除了string類型,string字段被拆分成兩種新的數據類型: text用於全文搜索的,而keyword用於關鍵詞搜索。
ElasticSearch字符串將默認被同時映射成text
和keyword
類型,將會自動創建類似下面的動態映射(dynamic mappings
):
{
"message": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
這就是造成部分字段還會自動生成一個與之對應的“keyword”字段的原因。
text
會被分詞器解析, 生成倒排索引, 支持模糊、精確查詢, 不用於排序, 很少用於聚合(significant text aggregation除外)
常用於全文檢索.
如果需要爲結構化內容, 比如 id、email、hostnames、狀態碼、標籤等進行索引,則推薦使用 keyword
類型以進行完全匹配. 比如我們需要查詢"已發貨"的訂單, 標記爲"已發佈"的文章等.
更多信息參考官方文檔
PUT my_index
{
"mappings": {
"properties": {
"full_name": {
"type": "text"
}
}
}
}
keyword
不進行分詞,直接索引, 支持模糊、精確查詢, 支持聚合
PUT my_index
{
"mappings": {
"properties": {
"tags": {
"type": "keyword"
}
}
}
}
ES會對"數值(numeric
)"類型的字段(比如, integet, long)進行優化以支持範圍(range)查詢. 但是, 不是所有的數值類型的數據都需要使用"數值"類型, 比如產品id, 會員id, ISDN(出版社編號), 這些很少會被進行範圍查詢, 通常都是精確匹配(term query).
keyword
類型的查詢通常比numeric
的要快, 如果不需要範圍查詢, 則建議使用keyword
類型.
如果不確定使用哪一種, 可以通過multi-field
同時設置keyword
和numeric
類型.
更多信息參考官方文檔
數值類型(numeric)
- 整型: byte, short, integer, long 這些與java中的類型一致
- 浮點型: float, half_float, scaled_float, double
類型 | 說明 | 取值範圍 |
---|---|---|
byte | 8位有符號整數 | -128 ~ 127 |
short | 16位有符號整數 | -32768 ~ 32767 |
integer | 32位有符號整數 | -2,147,483,648 ~ 2,147,483,647 即:-2^31 ~ 2^32 - 1 |
long | 64位有符號整數 | -2^63 ~ 2^63 - 1 |
float | 32位單精度IEEE 754浮點類型, 有限值, 24bits | 2^-149 ~ (2 - 2^-23) · 2^127 |
double | 64位雙精度IEEE 754浮點類型, 有限值, 53bits | 2^-1074 ~ (2 - 2^-52) · 2^1023 |
half_float | 16位半精度IEEE 754浮點類型, 有限值, 11bits | 2^-24 ~ 65504 |
scaled_float | 帶有縮放因子scaling_factor的浮點數, 可以當整型看待 |
比如:
PUT my_index
{
"mappings": {
"properties": {
"number_of_bytes": {
"type": "integer"
},
"time_in_seconds": {
"type": "float"
},
"price": {
"type": "scaled_float",
"scaling_factor": 100
}
}
}
}
上面我們定義了3個字段:
- number_of_bytes: 整型, integer
- time_in_seconds: 浮點型, float
- price: 帶有縮放因子scaling_factor的浮點數. 比如價格是99.99, 縮放因子爲100, 那麼存儲的值就是9999. 這種方式我們在數據庫中也經常使用, 比如我們在mysql中存儲價格, 只需要精確到分的話, 我們可以使用
decimal(12,2)
或者int
類型, 使用int類型可以節省空間而且不存在精度轉換問題, 但是我們必須在業務邏輯中使用縮放因子進行轉換, 而ES的scaled_float直接幫我們處理了.
對於上面展示的3種浮點類型(float
, half_float
, scaled_float
)來說, -0.00
和+0.00
是不同的值,使用term
查詢-0.00
時不會匹配+0.00
, 反之亦然。對於範圍查詢(range query)來說也是如此:如果上邊界是-0.00
則無法匹配+0.00
,如果下邊界是+0.00
則不會匹配-0.00
數值類型使用的注意事項:
- 在滿足業務需求的情況下, 儘量選擇範圍小的類型, 這與mysql等關係型數據庫的設計要求是一致的. 字段佔用的空間越小, 搜索和索引的效率越高(這個有點廢話, 數據量越小肯定越快了).
官方文檔說"storage is optimized based on the actual values that are stored", 難道一個integer類型的字段在存儲很小的值, 比如100, 的時候會只佔用1個字節而不是4個字節嗎? 這個與mysql倒是不同的. 在mysql的存儲中int就是4個字節, 而varchar纔會根據實際的內容佔用空間並記錄長度.
- 如果是浮點數, 則也要優先考慮使用scaled_float類型.
如果我們存儲商品價格只需要精確到分, 兩位小數點, 把縮放因子設置爲100, 那麼浮點價格99.99存儲時使用的是integer 類型, 佔用空間比float類型更小.
scaled_float在查詢時的的數據處理應該與mysql類似, 比如: SELECT * FROM products WHERE price > 99.99 * 100, 而不是 SELECT * FROM products WHERE price / 100 > 99.99, 後面一個寫法不符合mysql優化原則: 不要對欄位進行函數運算以及類型轉換.
未完待續....