实战 | 一步步排查基于业务场景的Elasticsearch难题!
1、题记
我们在实际的业务场景中做Elasticsearch开发时,免不了遇到这样、那样的问题。
《死磕Elasticsearch方法论》中,已经告诉大家相关问题的排查方法。
这一节,我们以具体的示例,解决基于业务场景的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。
1PUT my_index
2{
3 "mappings": {
4 "_doc": {
5 "properties": {
6 "date": {
7 "type": "date",
8 "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
9 }
10 }
11 }
12 }
13}
步骤3:常见日期类型的检索方式:
range时间区间检索:
1GET _search
2{
3 "query": {
4 "range" : {
5 "timestamp" : {
6 "gte": "2015-01-01 00:00:00",
7 "lte": "now",
8 "time_zone": "+01:00"
9 }
10 }
11 }
12}
参考:
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中的脚步语言。
应用举例:
1GET /_search
2{
3 "query": {
4 "bool" : {
5 "must" : {
6 "script" : {
7 "script" : {
8 "source": "doc['num1'].value > 1",
9 "lang": "painless"
10 }
11 }
12 }
13 }
14 }
15}
2、时间的返回接口
getDate().getMonthOfYear()
注意:
date.getMonthOfYear() == 11 返回11月;
date.getDayOfMonth() == 11 返回11日。
5、如何实现呢?
基于之前的分析,我的思路:
第一步:获取月;
第二步:获取日;
第三步:二者与。
具体实现:
1POST index_*/_search
2{
3 "size":100,
4 "_source": {
5 "includes": [
6 "title",
7 "create_time"
8 ]
9 },
10 "query": {
11 "bool" : {
12 "must" : [{
13 "script" : {
14 "script" : {
15 "inline": "doc['create_time'].getDate().getMonthOfYear() == 12",
16 "lang": "painless"
17 }
18 }
19 },
20 {
21 "script" : {
22 "script" : {
23 "inline": "doc['create_time'].getDate().getDayOfMonth() == 23",
24 "lang": "painless"
25 }
26 }
27 }
28 ]
29 }
30 }
31}
返回结果:
实际业务中,我以12月,23日作为检索条件验证的,我用的系统中没有11月11日的数据。
1{
2 "took": 5,
3 "timed_out": false,
4 "_shards": {
5 "total": 5,
6 "successful": 5,
7 "failed": 0
8 },
9 "hits": {
10 "total": 8536,
11 "max_score": 1,
12 "hits": [
13 {
14 "_index": "bak_index_v3",
15 "_type": "bke_type",
16 "_id": "AWCEDIuUYGOEa9MAzRvk",
17 "_score": 1,
18 "_source": {
19 "create_time": "2017-12-23 23:45:02",
20 "title": "世界道学网-道学文摘-唱道真言"
21 }
22 },
23 {
24 "_index": "bak_index_v3",
25 "_type": "bke_type",
26 "_id": "AWCD2bs4YGOEa9MAzRta",
27 "_score": 1,
28 "_source": {
29 "create_time": "2017-12-23 22:49:32",
30 "title": "新浪网-航天知识-飞向月球"
31 }
32 },
33 {
34 "_index": "bak_index_v3",
35 "_type": "baike_type",
36 "_id": "AWB_uk1jYGOEa9MAzRs4",
37 "_score": 1,
38 "_source": {
39 "create_time": "2017-12-23 03:36:44",
40 "title": "3DXXX需求"
41 }
42 },
43 {
44 "_index": "bak_index_v3",
45 "_type": "bke_type",
46 "_id": "AWCD2bhbYGOEa9MAzRtZ",
47 "_score": 1,
48 "_source": {
49 "create_time": "2017-12-23 22:49:31",
50 "title": "新浪网-知识-什么是全球定位系统"
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"
对应于我们的问题的解决方案:
1doc['create_time'].getDate().getMonthOfYear() == 11
2&& doc['create_time'].getDate(). getDayOfMonth () == 11
同时,这里告诉我们正确的英文关键词的搜索应该为:
Elasticsearch Filtering part of date ignoring Year like SQL DATEPART function
你我共深思。
更多知识点:重磅 | 死磕Elasticsearch方法论认知清单(全)