如何编写ES查询以查找字段的最大值和最小值之间的差异?
我是弹性搜索的新手, 在我的情况下,我提供了很多事件以及session_id和时间进行弹性搜索。 我的活动结构是
Event_name string `json:"Event_name"`
Client_id string `json:"Client_id"`
App_id string `json:"App_id"`
Session_id string `json:"Session_id"`
User_id string `json:"User_id"`
Ip_address string `json:"Ip_address"`
Latitude int64 `json:"Latitude"`
Longitude int64 `json:"Longitude"`
Event_time time.Time `json:"Time"`
我想根据所需的事件找到session_id的生命周期。 为此,我可以通过以下ES查询来检索特定session_id的最大Event_time和最小Event_time。
{
"size": 0,
"query": {
"match": {
"Session_id": "dummySessionId"
}
},
"aggs": {
"max_time": {
"max": {
"field": "Time"
}
},
"min_time":{
"min": {
"field": "Time"
}
}
}
}
但我确切想要的是(max_time - min_time) 如何为同一个????
编写ES查询答案 0 :(得分:2)
直到elasticsearch 1.1.1,这是不可能的对弹性搜索方面的两个聚合函数的结果进行任何算术运算。 如果您愿意,那么您应该从客户端那样做。
正如@eliasah所暗示的那样,这不可能通过脚本实现。
在即将推出的版本中,他们可能会添加此类设施。
答案 1 :(得分:1)
可以做到这一点。不确定性能,但它看起来很有效。 此功能属于实验性功能,可能会在以后的版本中完全更改或删除。
POST test_time
POST test_time/data/1
{"Session_id":1234,"Event_time":"2014-01-01T12:00:00"}
POST test_time/data/3
{"Session_id":1234,"Event_time":"2014-01-01T14:00:00"}
GET /test_time/_search
{
"size": 0,
"aggs": {
"by_user": {
"terms": {
"field": "Session_id"
},
"aggs": {
"session_lenght_sec": {
"scripted_metric": {
"map_script": "_agg['v'] = doc['Event_time'].value",
"reduce_script": "min = null; max = null; for (a in _aggs) {if (min == null || a.v < min) { min = a.v}; if (max == null || a.v > max) { max = a.v }}; return (max-min)/1000"
}
}
}
}
}
}
###### RESPONSE #######
{
...,
"aggregations": {
"by_user": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 1234,
"doc_count": 2,
"session_lenght_sec": {
"value": "7200"
}
}
]
}
}
}
答案 2 :(得分:0)
直接提供查询对您没有多大帮助,因此建议您阅读有关Script Fields和Scripting的文档。
答案 3 :(得分:0)
此答案绑定到Elasticsearch 7.8版本。 继续@pippobaudos的答案。自回答以来,Elasticsearch进行了一些重大更改。
聚合的类型为“ scripted_metric”(单击链接以了解更多信息),该类型具有新的子属性,例如init_script,map_script,combinet_script,reduce_script。其中,只有init_script是可选的。以下是修改后的查询。
"aggs": {
"cumulative":{
"scripted_metric": {
"init_script": {
"source": "state.stars = []"
},
"map_script": {
"source": "if (doc.containsKey('star_count')) { state.stars.add(doc['star_count'].value); }"
},
"combine_script": {
"source": "long min=9223372036854775807L,max=-9223372036854775808L; for (a in state.stars) {if ( a < min) { min = a;} if ( a > max) { max = a; }} return (max-min)"
},
"reduce_script": {
"source": "long max = -9223372036854775808L; for (a in states) { if (a != null && a > max){ max=a; } } return max "
}
}
}
}