热头条丨Elasticsearch 如何实现时间差查询?
问个问题啊,es能通过两个字段差值进行查询吗?类似select * from myindex where endtimes- starttime > 10这种?
——问题来源:死磕Elasticsearch 知识星球
【资料图】
那么问题来了,Elasticsearch 如何实现时间差的查询呢?
2、先说一下 MySQL 实现2.1 MySQL 表结构2.2 MySQL 样例数据2.3 MySQL 计算时间差?selecttimestampdiff(MINUTE,start_time,end_time)asspan fromtest;
结果如下:
结果 15代表 15 分钟的意思。
3、Elasticsearch 实现拆解3.1 创建索引PUTtest-index-001{"mappings":{"properties":{"starttime":{"type":"date"},"endtime":{"type":"date"}}}}3.2 插入数据
POSTtest-index-001/_bulk{"index":{"_id":1}}{"starttime":"2022-06-08T10:00:00Z","endtime":"2022-06-08T10:15:00Z"}3.3 方案一:直接类MySQL 查询实现
POSTtest-index-001/_search{"query":{"bool":{"filter":{"script":{"script":{"source":"doc["endtime"].date.minuteOfDay-doc["starttime"].date.minuteOfDay>=15","lang":"expression"}}}}}}
解读一下:
lang指的是脚本语言,这里使用的是:expression,不是 painless 无痛脚本,所以写法和往常会不同。
更多推荐查看:
3.4 方案二:ingest 预处理空间换时间实现核心使用的是:painless 无痛脚本。在对时间的脚本处理上略显笨拙(大家有好的方法可以交流)。
步骤1:时间字段转成字符串;步骤2:字符串转成 ZonedDateTime字段类型;步骤3:ZonedDateTime 字段类型转成 long长整形。步骤4:求解两个整形之差就可以了。实现如下代码所示:
PUT_ingest/pipeline/my_pipeline_20220618{"processors":[{"script":{"lang":"painless","source":"""Stringstart_datetime=ctx.starttime;ZonedDateTimestart_zdt=ZonedDateTime.parse(start_datetime);Stringend_datetime=ctx.endtime;ZonedDateTimeend_zdt=ZonedDateTime.parse(end_datetime);longstart_millisDateTime=start_zdt.toInstant().toEpochMilli();longend_millisDateTime=end_zdt.toInstant().toEpochMilli();longelapsedTime=end_millisDateTime-start_millisDateTime;ctx.span =elapsedTime/1000/60;"""}}]}POSTtest-index-001/_update_by_query?pipeline=my_pipeline_20220618{"query":{"match_all":{}}}POSTtest-index-001/_search{"query":{"range":{"span":{"gte":15}}}}
如上 update_by_query 的实现完全可以转换为预处理+setting环节的 default_pipeline 方式实现,确保写入环节直接生成span字段值,确保候选实现空间换时间,提高检索效率。
default_pipeline 实现如下:
PUTtest-20220619-10-02{"settings":{"default_pipeline":"my_pipeline_20220618"},"mappings":{"properties":{"start_time":{"type":"date"},"end_time":{"type":"date"}}}}###步骤2:导入数据PUTtest-20220619-10-02/_doc/1{"start_time":"2022-01-01T12:00:30Z","end_time":"2022-01-01T12:15:30Z"}###方案二优势地方:时间差值已经成为我们新的字段,直接用这个字段POSTtest-20220619-10-02/_search{"query":{"range":{"span":{"gte":15}}}}
如上实现,更简洁写法如下:
PUT_ingest/pipeline/my_pipeline_20220618_03{"processors":[{"script":{"lang":"painless","source":"""//createaInstantobjectInstantstart_instant=Instant.parse(ctx.starttime);//getmillisecondvalueusingtoEpochMilli()longstart_millisDateTime=start_instant.toEpochMilli();//createaInstantobjectInstantend_instant=Instant.parse(ctx.endtime);//getmillisecondvalueusingtoEpochMilli()longend_millisDateTime=end_instant.toEpochMilli();longelapsedTime=end_millisDateTime-start_millisDateTime;ctx.span =elapsedTime/1000/60;"""}}]}3.5 方案三:runtime_field 实时检索实现
POSTtest-index-001/_search{"fields":["*"],"runtime_mappings":{"span_value":{"type":"long","script":{"source":"emit((doc["endtime"].getValue().toInstant().toEpochMilli()-doc["starttime"].getValue().toInstant().toEpochMilli())/60000)"}}}}
核心:同样是转化为毫秒,然后做的计算。
注意:fields 要设置,否则数据 _source 下不显示。
4、小结关于 Elasticsearch 实现时间差查询,本文给出三种不同方案实现,视频解读如下。
从简洁程度推荐方案 1 或者方案 3。
从性能角度推荐方案 2 ——空间换时间,方案 2 可以优化为写入的时候指定 default_pipeline 全部预处理实现。
你的业务环境有没有遇到类似问题,你是如何实现的呢?
参考https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-expression.html
https://www.elastic.co/guide/en/elasticsearch/reference/5.0/modules-scripting-expression.html#datefield_api
https://www.elastic.co/guide/en/elasticsearch/painless/master/painless-datetime.html#_datetime_input_from_an_indexed_document
https://www.elastic.co/guide/en/elasticsearch/painless/current/painless-api-reference-shared-java-time.html
推荐阅读如何从0到1打磨一门 Elasticsearch 线上直播课?
重磅 | 死磕 Elasticsearch 方法论认知清单(2021年国庆更新版)
如何系统的学习 Elasticsearch ?
Elasticsearch 预处理没有奇技淫巧,请先用好这一招!
Elasticsearch的ETL利器——Ingest节点
更短时间更快习得更多干货!
和全球1600+Elastic 爱好者一起精进!
比同事抢先一步学习进阶干货!相关阅读
-
世界热推荐:今晚7:00直播丨下一个突破...
今晚19:00,Cocos视频号直播马上点击【预约】啦↓↓↓在运营了三年... -
NFT周刊|Magic Eden宣布支持Polygon网...
Block-986在NFT这样的市场,每周都会有相当多项目起起伏伏。在过去... -
环球今亮点!头条观察 | DeFi的兴衰与...
在比特币得到机构关注之后,许多财务专家预测世界将因为加密货币的... -
重新审视合作,体育Crypto的可靠关系才能双赢
Block-987即使在体育Crypto领域,人们的目光仍然集中在FTX上。随着... -
简讯:前端单元测试,更进一步
前端测试@2022如果从2014年Jest的第一个版本发布开始计算,前端开发... -
焦点热讯:刘强东这波操作秀
近日,刘强东发布京东全员信,信中提到:自2023年1月1日起,逐步为...