关于elasticsearch:Elasticsearch-每日一课存储一个-float-值到-long-字段会怎么样

2次阅读

共计 1830 个字符,预计需要花费 5 分钟才能阅读完成。

明天咱们要探讨的主题会让很多老手感到困惑,因为自身这个问题就挺难了解的。但如果你对 ES 比拟相熟,明天的内容也能够测试一下你对 ES 数据类型方面的常识是否可靠。

一、默认的 Numeric 类型

首先,咱们创立一个索引:

PUT orders/_doc/1
{"order_id": 1}

如上示例,利用 Dynamic Mapping,零碎会为主动为 orders 索引创立一个 Mapping,那么默认的状况下,order_id 这个字段会被推断为啥类型呢?

上面是这个 orders 索引的 Mapping:

# 获取 Mapping
GET orders/_mapping

# 后果:{
  "orders" : {
    "mappings" : {
      "properties" : {"order_id" : { "type" : "long"}
      }
    }
  }
}

如上示例,很显著 Dynamic Mapping 推断的 order_id 为 long 类型。

那如果咱们对这个 order_id 字段写入一些非整型数字会产生啥状况呢?在 Kibana 中执行以下命令来插入文档:

PUT orders/_doc/2
{"order_id": 2}

PUT orders/_doc/3
{"order_id": "3"}

PUT orders/_doc/4
{"order_id": 4.5}

PUT orders/_doc/5
{"order_id": "5.5"}

PUT orders/_doc/6
{"order_id": "六"}

文档 2 跟文档 1 类似,所以必定能够插入。但当咱们尝试把一个字符串、float,甚至字符串模式的 float 值存储到 long 类型字段时会产生啥呢?能够必定的是,除了文档 6,其余都能够胜利存储,但为啥呢?

二、coerce 对数据处理

默认的状况下,ES 将会用 coerce 来解决不合乎规定的数据。Coercion 会尝试转换不合乎字段类型的数据,例如:

  • 字符串会被转换到 numbers。
  • Float 会被截断,转换为 integer。

ok,有了 coerce,那咱们通过 search 接口获取到的 order_id 会是 1,2,3,4,5 吗?其实不然:

# 获取数据
GET orders/_search
{"query": { "match_all": {} }
}

# 后果
{"_shards" : {.....},
  "hits" : {
    ......
    "hits" : [
      {
        "_id" : "1",
        "_source" : {"order_id" : 1}
      },
      {
        "_id" : "2",
        "_source" : {"order_id" : 2}
      },
      {
        "_id" : "3",
        "_source" : {"order_id" : "3"}
      },
      {
        "_id" : "4",
        "_source" : {"order_id" : 4.5}
      },
      {
        "_id" : "5",
        "_source" : {"order_id" : "5.5"}
      }
    ]
  }
}

看到下面的后果,你是不是蒙圈了?不是说会数据转换解决的吗?如果此时再次查看 Mapping 的话,发现 order_id 的的确确是 long 类型的。

三、不会被扭转的 _source

上述的这个疑难其实很好解答,因为 ES 不会扭转 _source 的内容 。简略来说就是 _source 的数据其实存储在一个中央,而 order_id 这个字段的索引数据却存储在另外一个中央,它们不是混着(共用)的。简略来说就是,写入数据的时候,会把 _source 里的 order_id 拿进去,通过 coerce 进行解决,而后对解决后的后果进行索引操作。

能够通过对 order_id 字段做聚合操作来验证这个想法:

# 聚合操作
GET orders/_search
{
  "size": 0,
  "aggs": {
    "the_sum": {"sum": { "field": "order_id"}
    }
  }
}

# 后果
{
  ......
  "aggregations" : {
    "the_sum" : {"value" : 15.0}
  }
}

对 order_id 进行聚合操作,最终得出正确后果,能够证实其数据的类型为 long。

四、总结

最初须要留神的是,coerce 当前可能会被删除!!!对于这部分的信息,你能够参考这个 issue。怎么说呢,默认的状况上来改变用户输出的数据,其实不是一个太好的抉择,let it crash 不好吗?

另外,从这里例子中咱们能够加深对 Mapping 和索引了解。Mapping 其实是形容了索引的设置和各个字段的属性,但并没有太限度用户输出的 _source 是否严格与字段类型相匹配(默认的状况下)。

最初,如果你对 ES 感兴趣,欢送订阅我的《Elasticsearch 从入门到实际》小册。

正文完
 0