1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Elasticsearch 如何實(shí)現(xiàn)時(shí)間差查詢?

        共 8250字,需瀏覽 17分鐘

         ·

        2022-06-21 15:32

        1、Elasticsearch 線上實(shí)戰(zhàn)問(wèn)題

        問(wèn)個(gè)問(wèn)題啊,es能通過(guò)兩個(gè)字段差值進(jìn)行查詢嗎?類似select * from myindex where endtimes- starttime > 10這種?

        ——問(wèn)題來(lái)源:死磕Elasticsearch 知識(shí)星球

        那么問(wèn)題來(lái)了,Elasticsearch 如何實(shí)現(xiàn)時(shí)間差的查詢呢?

        2、先說(shuō)一下 MySQL 實(shí)現(xiàn)

        2.1 MySQL 表結(jié)構(gòu)

        2.2 MySQL 樣例數(shù)據(jù)

        2.3 MySQL 計(jì)算時(shí)間差?

        select timestampdiff(MINUTE, start_time, end_time) as span from test;

        結(jié)果如下:

        結(jié)果 15 代表 15 分鐘的意思。

        3、Elasticsearch 實(shí)現(xiàn)拆解

        3.1 創(chuàng)建索引

        PUT test-index-001
        {
          "mappings": {
            "properties": {
              "starttime": {
                "type""date"
              },
              "endtime": {
                "type""date"
              }
            }
          }
        }

        3.2 插入數(shù)據(jù)

        POST test-index-001/_bulk
        {"index":{"_id":1}}
        {"starttime":"2022-06-08T10:00:00Z","endtime":"2022-06-08T10:15:00Z"}

        3.3 方案一:直接類MySQL 查詢實(shí)現(xiàn)

        POST test-index-001/_search
        {
          "query": {
            "bool": {
              "filter": {
                "script": {
                  "script": {
                    "source""doc['endtime'].date.minuteOfDay - doc['starttime'].date.minuteOfDay >= 15",
                    "lang""expression"
                  }
                }
              }
            }
          }
        }

        解讀一下:

        lang 指的是腳本語(yǔ)言,這里使用的是:expression,不是 painless 無(wú)痛腳本,所以寫(xiě)法和往常會(huì)不同。

        更多推薦查看:

        3.4 方案二:ingest 預(yù)處理空間換時(shí)間實(shí)現(xiàn)

        核心使用的是:painless 無(wú)痛腳本。在對(duì)時(shí)間的腳本處理上略顯笨拙(大家有好的方法可以交流)。

        • 步驟1:時(shí)間字段轉(zhuǎn)成字符串;
        • 步驟2:字符串轉(zhuǎn)成 ZonedDateTime 字段類型;
        • 步驟3:ZonedDateTime 字段類型轉(zhuǎn)成 long 長(zhǎng)整形。
        • 步驟4:求解兩個(gè)整形之差就可以了。

        實(shí)現(xiàn)如下代碼所示:

        PUT _ingest/pipeline/my_pipeline_20220618
        {
          "processors": [
            {
              "script": {
                "lang""painless",
                "source""""
                
                String start_datetime = ctx.starttime; 
                ZonedDateTime start_zdt = ZonedDateTime.parse(start_datetime); 
                
                String end_datetime =ctx.endtime; 
                ZonedDateTime end_zdt = ZonedDateTime.parse(end_datetime); 

                long start_millisDateTime = start_zdt.toInstant().toEpochMilli();
                long end_millisDateTime = end_zdt.toInstant().toEpochMilli();
                long elapsedTime = end_millisDateTime - start_millisDateTime;
              
                ctx.span = elapsedTime/1000/60;

                """

              }
            }
          ]
        }

        POST test-index-001/_update_by_query?pipeline=my_pipeline_20220618
        {
          "query": {
            "match_all": {}
          }
        }

        POST test-index-001/_search
        {
          "query": {
            "range": {
              "span": {
                "gte": 15
              }
            }
          }
        }

        如上 update_by_query 的實(shí)現(xiàn)完全可以轉(zhuǎn)換為預(yù)處理+setting環(huán)節(jié)的 default_pipeline 方式實(shí)現(xiàn),確保寫(xiě)入環(huán)節(jié)直接生成span字段值,確保候選實(shí)現(xiàn)空間換時(shí)間,提高檢索效率。

        default_pipeline 實(shí)現(xiàn)如下:

        PUT test-20220619-10-02
        {
          "settings": {
            "default_pipeline""my_pipeline_20220618"
          },
          "mappings": {
            "properties": {
              "start_time": {
                "type""date"
              },
              "end_time": {
                "type""date"
              }
            }
          }
        }


        ### 步驟2:導(dǎo)入數(shù)據(jù)
        PUT test-20220619-10-02/_doc/1
        {
          "start_time""2022-01-01T12:00:30Z",
          "end_time""2022-01-01T12:15:30Z"


        ### 方案二優(yōu)勢(shì)地方:時(shí)間差值已經(jīng)成為我們新的字段,直接用這個(gè)字段
        POST test-20220619-10-02/_search
        {
          "query": {
            "range": {
              "span": {
                "gte": 15
              }
            }
          }
        }

        如上實(shí)現(xiàn),更簡(jiǎn)潔寫(xiě)法如下:

        PUT _ingest/pipeline/my_pipeline_20220618_03
        {
          "processors": [
            {
              "script": {
                "lang""painless",
                "source""""
                
                  // create a Instant object
                Instant start_instant = Instant.parse(ctx.starttime);
         
                // get millisecond value using toEpochMilli()
                long start_millisDateTime = start_instant.toEpochMilli();
                
                // create a Instant object
                Instant end_instant= Instant.parse(ctx.endtime);
         
                // get millisecond value using toEpochMilli()
                long end_millisDateTime = end_instant.toEpochMilli();
                long elapsedTime = end_millisDateTime - start_millisDateTime;
                ctx.span = elapsedTime/1000/60;

                """

              }
            }
          ]
        }

        3.5 方案三:runtime_field 實(shí)時(shí)檢索實(shí)現(xiàn)

        POST test-index-001/_search
        {
          "fields": [
            "*"
          ],
          "runtime_mappings": {
            "span_value": {
              "type""long",
              "script": {
                "source""emit((doc['endtime'].getValue().toInstant().toEpochMilli() - doc['starttime'].getValue().toInstant().toEpochMilli())/60000)"
              }
            }
          }
        }

        核心:同樣是轉(zhuǎn)化為毫秒,然后做的計(jì)算。

        注意:fields 要設(shè)置,否則數(shù)據(jù) _source 下不顯示。

        4、小結(jié)

        關(guān)于 Elasticsearch 實(shí)現(xiàn)時(shí)間差查詢,本文給出三種不同方案實(shí)現(xiàn),視頻解讀如下。

        從簡(jiǎn)潔程度推薦方案 1 或者方案 3。

        從性能角度推薦方案 2 ——空間換時(shí)間,方案 2 可以優(yōu)化為寫(xiě)入的時(shí)候指定 default_pipeline 全部預(yù)處理實(shí)現(xiàn)。

        你的業(yè)務(wù)環(huán)境有沒(méi)有遇到類似問(wèn)題,你是如何實(shí)現(xiàn)的呢?

        參考

        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

        推薦閱讀

        1. 如何從0到1打磨一門 Elasticsearch 線上直播課?

        2. 重磅 | 死磕 Elasticsearch 方法論認(rèn)知清單(2021年國(guó)慶更新版)

        3. 如何系統(tǒng)的學(xué)習(xí) Elasticsearch ?

        4. Elasticsearch 預(yù)處理沒(méi)有奇技淫巧,請(qǐng)先用好這一招!

        5. Elasticsearch的ETL利器——Ingest節(jié)點(diǎn)

        短時(shí)間快習(xí)得多干貨!

        和全球 1600+ Elastic 愛(ài)好者一起精進(jìn)!


        比同事搶先一步學(xué)習(xí)進(jìn)階干貨!
        瀏覽 52
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            一起草91 | 把美女操出水 | 成人A片区 | 天天操操操 | 天躁夜夜躁2021aa91 | 欧美丰满熟妇BBBBBB小短人 | 亚洲AV无码国产综合专区 | 一区二区三区无码区 | 99久草 | 38色综合 |