前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Elasticsearch 线上问题实战——如何借助 painless 更新时间?

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

作者头像
铭毅天下
发布2021-10-20 16:12:09
1.4K0
发布2021-10-20 16:12:09
举报
文章被收录于专栏:铭毅天下铭毅天下

1、线上问题

昨晚 11:14 收到球友周大哥的问题:

老大,请教个问题。你用painless操作过@timestamp字段吗?比如我获取了当前timestamp后,想要减去5分钟, 这个怎么写?ctx._source['@timestamp'] 是get当前的timestamp,后面operator要怎么写?

2、问题拆解

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

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

第三:看问题。

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

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

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

3、开搞,实战一把

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

代码语言:javascript
复制
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 仿真执行一下:

代码语言:javascript
复制
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"
      }
    }
  ]
}

报错啦!报错如下:

类型错误。

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

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

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

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

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

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

那就翻翻看吧。

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

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

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

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

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

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

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

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

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

  • 在日期时间格式上述三种不同类型之间切换通常是实现脚本目标所必需的。
  • 脚本中的典型应用是:将数字(numeric)或字符串(string)格式切换为 complex 日期格式,基于complex 日期格式做修改或比较,然后将其切换回数字或字符串日期格式进行存储或返回结果。

继续开搞吧:

代码语言:javascript
复制
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

上结果:

至此,问题解决完毕。

4、核心实现的语法解读

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

代码语言:javascript
复制
String datetime = ctx.start_date;

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

代码语言:javascript
复制
ZonedDateTime zdt = ZonedDateTime.parse(datetime);

第三:执行减法操作。

代码语言:javascript
复制
zdt = zdt.minusMinutes(5);

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

代码语言:javascript
复制
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

推荐

1、重磅 | 死磕 Elasticsearch 方法论认知清单(2021年国庆更新版)

2Elasticsearch 7.X 进阶实战私训课(口碑不错)

3、Elasticsearch 预处理没有奇技淫巧,请先用好这一招!

4、干货 | Elasticsearch7.X Scripting脚本使用详解

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-10-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 铭毅天下Elasticsearch 微信公众号,前往查看

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

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、线上问题
  • 2、问题拆解
  • 3、开搞,实战一把
    • 3.1 步骤 1:创建索引,并导入一批含日期类型的数据。
      • 3.2 步骤 2:更新处理尝试。
        • 3.3 步骤 3:换个思路,从脚本部分再切入。
        • 4、核心实现的语法解读
        • 5、小结
        • 参考
        • 推荐
        相关产品与服务
        Elasticsearch Service
        腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档