Elasticsearch 线上问题实战——如何借助 painless 更新时间?

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 老大,请教个问题。你用painless操作过@timestamp字段吗?比如我获取了当前timestamp后,想要减去5分钟, 这个怎么写?ctx._source['@timestamp'] 是get当前的timestamp,后面operator要怎么写?

2、问题拆解

第一:晚上 11:14发出问题,说明问题很着急,极大可能是线上问题。


第二:球友周大哥是资深架构师,可能问题会有一点弯或是有一些不常用的细节。


第三:看问题。


一句话概括问题:对于给定的时间字段值,用 painless 脚本实现减去 5 分钟的处理。


painless 脚本的处理,我想到的是:ingest 预处理管道的使用。


当然之前我们也讲过还有直接处理脚本的方式,但是:结合管道预处理会更方便、更好理解。


3、开搞,实战一把

3.1 步骤 1:创建索引,并导入一批含日期类型的数据。

DELETE logs

PUT logs

{

 "mappings": {

   "properties": {

     "name": {

       "type": "text"

     },

     "start_date": {

       "type": "date"

     },

     "close_date": {

       "type": "date"

     }

   }

 }

}

PUT logs/_bulk?refresh

{"index":{"_id":1}}

{"name":"Person AA","start_date":"2015-05-06T02:49:40.894Z","close_date":"2015-11-01T18:10:30Z"}

{"index":{"_id":2}}

{"name":"Person CC","start_date":"2015-05-06T02:49:40.894Z","close_date":"2015-11-02T13:10:30Z"}

3.2 步骤 2:更新处理尝试。

我的初始理解,获取时间,然后 - 5(代表 5 分钟的意思),不就搞定了吗。


试试看?simulate 仿真执行一下:


POST /_ingest/pipeline/_simulate

{

 "pipeline": {

   "description": "_description",

   "processors": [

     {

       "script": {

         "description": "add time",

         "lang": "painless",

         "source": """

            ctx.start_date = ctx.start_date - 5

         """

       }

     }

   ]

 },

 "docs": [

   {

     "_index": "index",

     "_id": 1,

     "_source": {

       "name": "Person AA",

       "start_date": "2015-05-06T02:49:40.894Z",

       "close_date": "2015-11-01T18:10:30Z"

     }

   }

 ]

}

报错啦!报错如下:

image.png

类型错误。


是的,一种方案就是继续:在类型转换上下功夫。搞定类型转换就搞定上面的脚本。


我做了很多尝试,效果不大理想。看到这里的同学,可以自己尝试一下,欢迎留言交流。


这时候,我想:是不是得转换一下思路。


3.3 步骤 3:换个思路,从脚本部分再切入。

官方文档的如下部分,引起我的注意:

image.png

换个思路思考,既然:官方文档拿出 1 篇文章的篇幅讲解 Datetime 时间类型的 painless 的应用,说明这里还是有“文章”的。


那就翻翻看吧。


宏观上看:在 painless “无痛”脚本中,Datetime 时间类型共有如下三种类型:


类型1:numeric 时间戳类型,举例:

image.png

本质上,这是一种 long 类型的值。


类型2:string 类型。举例:"2015-05-06T02:49:40.894Z"。


我们上面写入的数据就是这种类型。


类型3:complex 类型。这种我们不常见,它是一种复杂对象类型。在 painless 中通常为:ZonedDateTime。


单看 ZonedDateTime 干巴巴的,不知道是啥意思?


但是,跳转链接看到如下内容的时候,顿时感觉豁然开朗。

image.png

要强调的是如下一段话,切中选型要害!


在日期时间格式上述三种不同类型之间切换通常是实现脚本目标所必需的。


脚本中的典型应用是:将数字(numeric)或字符串(string)格式切换为 complex 日期格式,基于complex 日期格式做修改或比较,然后将其切换回数字或字符串日期格式进行存储或返回结果。


继续开搞吧:


PUT /_ingest/pipeline/time_pipeline

{

 "processors": [

   {

     "script": {

       "description": "add time",

       "lang": "painless",

       "source": """

          String datetime = ctx.start_date;

          ZonedDateTime zdt = ZonedDateTime.parse(datetime);

          zdt = zdt.minusMinutes(5);

          ctx.start_date = zdt;

         """

     }

   }

 ]

}

POST logs/_update_by_query?pipeline=time_pipeline

{

 "query": {

   "match_all": {}

 }

}

GET logs/_search

上结果:

image.png

至此,问题解决完毕。


4、核心实现的语法解读

第一:获取时间字段,赋值为字符串。


String datetime = ctx.start_date;

第二:字符串类型转 complex 类型。


ZonedDateTime zdt = ZonedDateTime.parse(datetime);

第三:执行减法操作。


zdt = zdt.minusMinutes(5);

第四:减法操作后的结果重新赋值回去。


ctx.start_date = zdt;

有了 painless 脚本,后面借助:update_by_query 批量更新结合 painless 脚本就能方便的实现已有数据的更新操作。


更多 Datetime painless 脚本的使用细节,推荐参考阅读文末的官方链接地址。


5、小结

第一:对于不是特别熟悉或者非常小众的知识点,找到突破口很关键。找到了突破口,就找到了解决问题的思路。


第二:一个小的知识点,能引发很多知识点甚至知识链条。


就拿本文举例:我自己之前肯定也遇到过日期时间的查询、聚合、更新处理操作,但是没有系统化的翻看过 painless 时间处理的文档。所以,当遇到新的问题的时候,依然是没有方法论,只是凭经验去猜、尝试,“猜、尝试”花的时间总体算下来比查看官方文档还要长。


“前事不忘后事之师”,今天的实践和小结尤其方法论部分是未来学习、实战环节要改进的点。


参考

https://www.elastic.co/guide/en/elasticsearch/painless/master/painless-datetime.html


https://www.elastic.co/guide/en/elasticsearch/painless/master/painless-api-reference-shared-java-time.html#painless-api-reference-shared-ZonedDateTime

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
5月前
|
存储 人工智能 自然语言处理
ElasticSearch实战指南必知必会:安装分词器、高级查询、打分机制
ElasticSearch实战指南必知必会:安装分词器、高级查询、打分机制
ElasticSearch实战指南必知必会:安装分词器、高级查询、打分机制
|
4月前
|
安全 大数据 API
elasticsearch|大数据|elasticsearch的api部分实战操作以及用户和密码的管理
elasticsearch|大数据|elasticsearch的api部分实战操作以及用户和密码的管理
63 0
|
7月前
|
监控 搜索推荐 Java
elasticsearch入门实战
elasticsearch入门实战
63 1
|
6月前
|
存储 关系型数据库 数据库
ElasticSearch深度解析入门篇:高效搜索解决方案的介绍与实战案例讲解,带你避坑
ElasticSearch深度解析入门篇:高效搜索解决方案的介绍与实战案例讲解,带你避坑
ElasticSearch深度解析入门篇:高效搜索解决方案的介绍与实战案例讲解,带你避坑
|
4月前
elasticsearch使用 scroll 滚动分页实战实例
elasticsearch使用 scroll 滚动分页实战实例
132 0
|
1月前
|
消息中间件 Java 关系型数据库
【二十】springboot整合ElasticSearch实战(万字篇)
【二十】springboot整合ElasticSearch实战(万字篇)
209 47
|
8月前
|
JSON 数据挖掘 数据格式
|
4月前
|
JSON 数据格式
elasticsearch 实战(二)
elasticsearch 实战
35 0
|
4月前
|
JSON Java API
elasticsearch 实战(一)
elasticsearch 实战
67 0
|
4月前
|
JavaScript Java 开发工具
ElasticSearch实战 之 es的安装和使用
ElasticSearch实战 之 es的安装和使用
140 0

热门文章

最新文章