前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Elasticsearch 数值类型也能存String 类型,有点意思~

Elasticsearch 数值类型也能存String 类型,有点意思~

原创
作者头像
南非骆驼说大数据
发布2022-01-02 12:20:01
2.2K2
发布2022-01-02 12:20:01
举报

一、前言|

最近经常遇到遇到某个客户问数值类型的字段也能存字符串,或者说已经将字段类型设置成了float,但是实际存储的仍然是字符串,该如何解决,今天花点时间我们来梳理整个流程。

二、实际演练

1,定义一个索引mapping,并指定类型为float.单精度浮点型

PUT nginxindex
{
  "mappings": {
    "properties": {
      "price":{
        "type": "float"
      }
    }
  }
}

2,写入几个文档,看看效果

POST nginxindex/_doc
{
  "price":4.68        //数字类型
}

POST nginxindex/_doc
{
  "price": "4.69"      //字符串类型
}

POST nginxindex/_doc
{
  "price": "free for charge"    //字符串类型
}

3,对比结果

第一个,正常写入,有返回,

第二个,正常写入,有返回,

第三个,无法写入,报错提示。提示如下图所示

第三个报错
第三个报错

这个报错大概就是无法解析字符串内容到floa类型的type.这个比较容易理解,但是第二个文档那个字符串类型数字又能写入,这又是为何?那么这也是本节要关注的内容,也是前面客户需要解决的问题:

三、问题原因

用户在存储字符串形式的数字,无论是那种数字类型,都能默认识别并存储,那么最终客户在终端搜索的时候会出现很多返回结果数量不一致的问题。这个是什么原因呢?我们看一下官网,翻译如下:

数据并不总是干净的。根据它的生成方式,一个数字可能在JSON体中呈现为一个真正的JSON数字,例如。5,但它也可能呈现为一个字符串,例如。“5”。或者,一个应该是整数的数字可以呈现为浮点,例如5.0,甚至“5.0”。

需要配置强制程序来清理脏值,以适应字段的数据类型。具体参考如下链接:

https://www.elastic.co/guide/en/elasticsearch/reference/current/coerce.html#coerce

解决方案:就是在索引的mapping字段属性定义里,加一个coerce参数,并将其值设置为false.默认为true.

四、再次实践

PUT nginxnewindex
{
  "mappings": {
    "properties": {
      "price":{
        "type": "float",
        "coerce": false        //定义mapping
      }
    }
  }
}

POST nginxnewindex/_doc        //写入几个文档
{
  "price":4.68
}

POST nginxnewindex/_doc      //写入报错,
{
  "price": "4.69"
}

结果会发现,第三个文档,写入报错,截图如下:

字段解析错误
字段解析错误

错误提示也是说你定义一个float类型的字段,但是写入的是字符串。

那么这样的话,用户就能第一时间发现写入报错信息,及时扭转前端写入格式,以防后续影响业务了。那么这就是这个严格匹配参数的作用。

五、实际生产环境中,如何平滑解决用户字段类型错误?

mapping字段类型一旦定义,就不能再修改。那么实际用户生产环境,新数据可以通过修改新索引mapping参数解决。那么对于存量的索引数据,如何实现平滑更改呢。没错,大家想到的是reindex.再造索引。还是以本文前面报错的索引为列,如何实现字符串类型的float转换为纯float数字类型。

先看源索引的文档类型,price是字符串类型,后面要实现更改为float.

1,先创建一个目标索引,指定mapping参数

PUT nginxnewindex2
{
  "mappings": {
    "properties": {
      "price":{
        "type": "float",
        "coerce": false
      }
    }
  }
}

2, 执行reindex拷贝,这里有问题,注意

POST _reindex
{
  "source": {
    "index": "nginxindex"
  },
  "dest": {
    "index": "nginxnewindex2"
  }
}

返回报错如下:

reindex索引报错
reindex索引报错

这个错误大家都很明白了,就是写入的是字符串,但是实际目标存储的字段类型是数字类型,解析失败。reindex也中断。

因此,reindex在某些场景下是有限制的。两个索引mapping不一致的问题,会导致索引同步失败。

那么有没有一种办法,将存量索引的字段类型进行更改,然后再拷贝到目标索引呢? 答案是有的,这里要用到pipeline,管道预处理。就是在reindex拷贝之前,将源索引的字段类型先进行更改,然后再写入目标索引。

六、Reindex+pipeline预处理方式实现存量索引字段类型的更改并拷贝

需求:实现reindex的时候,转化源索引格式到float.

第一步,创建一个processors


PUT _ingest/pipeline/my-pipeline-id
{
  "description": "converts the content of the price field to an float",
  "processors" : [
    {
      "convert" : {
        "field" : "price",
        "type": "float"
      }
    }
  ]
}

第二步:创建一个目标索引

PUT nginxnewindex2
{
  "mappings": {
    "properties": {
      "price":{
        "type": "float",
        "coerce": false
      }
    }
  }
}

第三步:执行reindex+pipeline

POST _reindex
{
  "source": {
    "index": "nginxindex"    //源索引,要改造的索引
  },
  "dest": {
    "index": "nginxnewindex2",
    "pipeline": "my-pipeline-id"
  }
}

返回如下:没有报错,执行成功。

返回成功
返回成功

那么我们看看目标拷贝的索引的mapping,看看新的字段类型是否变成强float了。如下:更改成功。

那么至此,彻底解决客户这个问题。问题整理完毕。以后两个字段类型不一样需要转格式,大家也可以这么操作。

七、总结

本文从一个实际生产案列出发,分析剖解解决了一个字段精确值的问题,以及平滑解决存量索引字段类型转换的问题,因该方法比较经典,特梳理整理了一下,希望能帮到有需求的人们。

完。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前言|
  • 二、实际演练
  • 三、问题原因
  • 四、再次实践
  • 五、实际生产环境中,如何平滑解决用户字段类型错误?
  • 六、Reindex+pipeline预处理方式实现存量索引字段类型的更改并拷贝
  • 七、总结
相关产品与服务
Elasticsearch Service
腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档