Elasticsearch中字段類型(Field Type)詳解

字段類型詳解

字符串: text, keyword

5.0以後,string類型有重大變更,移除了string類型,string字段被拆分成兩種新的數據類型: text用於全文搜索的,而keyword用於關鍵詞搜索。

ElasticSearch字符串將默認被同時映射成textkeyword類型,將會自動創建類似下面的動態映射(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同時設置keywordnumeric類型.

更多信息參考官方文檔

數值類型(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

數值類型使用的注意事項:

  1. 在滿足業務需求的情況下, 儘量選擇範圍小的類型, 這與mysql等關係型數據庫的設計要求是一致的. 字段佔用的空間越小, 搜索和索引的效率越高(這個有點廢話, 數據量越小肯定越快了).

官方文檔說"storage is optimized based on the actual values that are stored", 難道一個integer類型的字段在存儲很小的值, 比如100, 的時候會只佔用1個字節而不是4個字節嗎? 這個與mysql倒是不同的. 在mysql的存儲中int就是4個字節, 而varchar纔會根據實際的內容佔用空間並記錄長度.

  1. 如果是浮點數, 則也要優先考慮使用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優化原則: 不要對欄位進行函數運算以及類型轉換.

未完待續....

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章