天天看點

實戰 | 一步步排查基于業務場景的Elasticsearch難題!

2、上問題

請問下es可以在date字段上查詢月日嗎 下單時間字段類型是date,想查詢每年11月11日下單的記錄?有什麼辦法可以zh直接查?

原文連結:

https://elasticsearch.cn/question/3649

3、搜尋已有知識儲備

步驟1:腦海中顯現:ES中有哪些資料類型?ES支援哪些資料類型。

此處,我個人認為,沒必要記住。

但是,要知道,從哪裡查?

記住,查詢方法如下:

在Google或者Bing國際版輸入:“elasticsearch data type”

相關連結:

http://t.cn/REjyfxa

步驟2:ES中date字段時如何定義的?

在核心的資料類型部分,就介紹了ES中的Date類型:

資料類型分為三種:

1)字元串類型如: “2015-01-01” or “2015/01/01 12:10:30”.

2)長整型,以毫秒度量:1520256456000

3)整型,以秒度量:1520256456。

PUT my_index

{

 "mappings": {

   "_doc": {

     "properties": {

       "date": {

         "type":   "date",

         "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"

       }

     }

   }

 }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

步驟3:常見日期類型的檢索方式:

range時間區間檢索:

GET _search

   "query": {

       "range" : {

           "timestamp" : {

               "gte": "2015-01-01 00:00:00",

               "lte": "now",

               "time_zone": "+01:00"

           }

參考:

http://t.cn/RcWM2Py

步驟4:如何擷取日期中指定的年、月、日檢索?

能想到的是什麼呢——的确,我也沒這麼用過。

注意:此時一定要用英文去檢索。

在Google或者Bing國際版或者Stackoverflow中輸入:“elasticsearch date get month“。

看看網友的思路:

傳回如下:

http://t.cn/REjVkGW http://t.cn/REjfh8z

初步,确定解決方案。

結合:script檢索+ getDate().getMonthOfYear()接口實作條件檢索。

4、敲黑闆——知識點

1、script檢索

一種基于 Painless腳本語言的檢索, Painless 腳本語言是簡單、安全應用于Elasticsearch中的腳步語言。

應用舉例:

GET /_search

       "bool" : {

           "must" : {

               "script" : {

                   "script" : {

                       "source": "doc['num1'].value > 1",

                       "lang": "painless"

                    }

               }

14

15

2、時間的傳回接口

getDate().getMonthOfYear()

注意:

date.getMonthOfYear() == 11 傳回11月;

date.getDayOfMonth() == 11 傳回11日。

5、如何實作呢?

基于之前的分析,我的思路:

第一步:擷取月;

第二步:擷取日;

第三步:二者與。

具體實作:

POST index_*/_search

 "size":100,

 "_source": {

 "includes": [

 "title",

 "create_time"

 ]

 },

 "query": {

 "bool" : {

 "must" : [{

 "script" : {

 "inline": "doc['create_time'].getDate().getMonthOfYear() == 12",

 "lang": "painless"

 {

 "inline": "doc['create_time'].getDate().getDayOfMonth() == 23",

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

傳回結果:

實際業務中,我以12月,23日作為檢索條件驗證的,我用的系統中沒有11月11日的資料。

 "took": 5,

 "timed_out": false,

 "_shards": {

 "total": 5,

 "successful": 5,

 "failed": 0

 "hits": {

 "total": 8536,

 "max_score": 1,

 "hits": [

 "_index": "bak_index_v3",

 "_type": "bke_type",

 "_id": "AWCEDIuUYGOEa9MAzRvk",

 "_score": 1,

 "create_time": "2017-12-23 23:45:02",

 "title": "世界道學網-道學文摘-唱道真言"

 "_id": "AWCD2bs4YGOEa9MAzRta",

 "create_time": "2017-12-23 22:49:32",

 "title": "新浪網-航天知識-飛向月球"

 "_type": "baike_type",

 "_id": "AWB_uk1jYGOEa9MAzRs4",

 "create_time": "2017-12-23 03:36:44",

 "title": "3DXXX需求"

 "_id": "AWCD2bhbYGOEa9MAzRtZ",

 "create_time": "2017-12-23 22:49:31",

 "title": "新浪網-知識-什麼是全球定位系統"

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

6、小結

對于不熟悉的業務場景,可以通過檢索英文關鍵詞,通過Google、stackoverflow等最快找到解決方案。此處,切記:不要盲目用中文檢索。

使用完以後,一定要形成知識點總結,便于以後的觸類旁通。

參考:腳本檢索——

http://t.cn/R3nxhwW

7、這就完了嗎?

有沒有更便捷的方法。

這裡,後期檢索的時候,發現如下不需要bool檢索的更高效的解決方案:

https://goo.gl/EhtJA2

核心的一行腳本:

“script”: “doc.ActivityDate.date.getMonthOfYear() == 12 && doc.ActivityDate.date.getDayOfMonth() == 9”

對應于我們的問題的解決方案:

doc['create_time'].getDate().getMonthOfYear() == 11

&&  doc['create_time'].getDate(). getDayOfMonth () == 11

同時,這裡告訴我們正确的英文關鍵詞的搜尋應該為:

Elasticsearch Filtering part of date ignoring Year like SQL DATEPART function

你我共深思。