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优化原则: 不要对栏位进行函数运算以及类型转换.

未完待续....

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