开发者社区> 铭毅天下> 正文

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

简介: 老大,请教个问题。你用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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
心中有“树”!图文并茂介绍数据结构中常见的树(二)
计算机科学家尼古拉斯·沃斯(Niklaus Wirth)曾说过:编程=数据结构+算法 ,可见数据结构在编程中的重要性。
5 0
手撸一款简单高效的线程池(五)
在之前的内容中,我们给大家介绍了 C++实现线程池过程中的一些常用线优化方案,并分析了不同机制使用时的利弊。这一篇,是线程池系列的最后一章。我们会介绍一下 CGraph 中的 threadpool 如何使用,给出性能对比,并对接下来的工作做一些展望。让我们在线程池性能优化和功能提升的道路上,越走越远。
5 0
心中有“树”!图文并茂介绍数据结构中常见的树(一)
提到数据结构中的树(Tree) ,大家应该都不陌生,相关书籍中都有大段篇幅的介绍,刷 Leetcode 的时候会遇到很多相关问题。很多人往往会用 “手写红黑树” 来形容面试难度很高。
10 0
在函数中使用局部变量并且通过局部变量返回函数值的方案来了
感谢小游戏可视化体验官群中的一位叫做“@天羽地王”的朋友提供的思路。本文内容主要包括如何在函数中使用局部变量并且通过局部变量来返回函数的结果值。
8 0
微信小游戏推广运营专业术语汇总
本文内容包括与微信小游戏运营推广相关的专业术语的汇总和解释。作为一个游戏开发者,不光要知道如何做游戏,也要知道如何让别人玩自己做的游戏。
4 0
心中有“树”!图文并茂介绍数据结构中常见的树(三)
在前面两篇文章中,我们简要介绍了数据结构中的各种【树】在搜索、数据库等领域的使用场景,希望对大家有所帮助。
11 0
如何在小游戏制作工具中使用云函数
本节试图以最简单的方式带你了解如何在小程序后台申请和开通云开发服务,创建并编写第一个云函数并在小游戏制作工具中对其进行调用。
10 0
Win系统 - 重装系统(微PE、MSDN镜像)【绝对纯净】
Win系统 - 重装系统(微PE、MSDN镜像)【绝对纯净】
14 0
Vue入门 基本使用 与 事务管理【1】
Vue入门 基本使用 与 事务管理【1】
9 0
+关注
348
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载