Elasticsearch Painless - 按字段对所有文档进行分组,并对所有值进行计算
Elasticsearch Painless - Group all doucuments by a field, and do calculation on all values
我有 'vehicles' 索引模式,每个文档都有一个车牌号 ('plateNo')、'position' 和 'date' 字段。作为测试,我想按车牌号对该索引中的所有文档进行分组,然后按日期对文档进行排序,最后计算每辆车移动的距离,并将每两个位置之间的绝对差相加。
例如:
plateNo
position
date
vehicle 1
1
May 16, 2021 @ 15:55:37
vehicle 2
7
May 16, 2021 @ 15:55:05
vehicle 1
5
May 16, 2021 @ 15:54:30
vehicle 2
10
May 16, 2021 @ 15:53:01
vehicle 1
2
May 16, 2021 @ 15:50:41
的输出必须是
plateNo
distance
vehicle 1
abs(5 - 2) + abs(1 - 5) = 7
vehicle 2
abs(7 - 10) = 3
我如何使用 Painless 做到这一点? - 快速响应很重要,文档数量非常大
谢谢
假设:
- 同一车辆的数据存在于单个分片上
- 映射中定义的日期格式为'epoch_millis'
- 如果车辆只有一次进入,则其距离将为零
使用的聚合: scripted_metric
步骤:
- Init: 初始化了一个 TreeMap 用于存储 timestamp 作为 key 和 pos 作为 value
- Map: 将timestamp & pos的值放入TreeMap
- 收集:获取值并计算位置差(pos按时间戳排序返回)
- 减少: Return距离
示例查询:
GET vehicle/_search
{
"size": 0,
"aggs": {
"vehicles": {
"terms": {
"field": "vehicle",
"size": 10
},
"aggs": {
"distance": {
"scripted_metric": {
"init_script": "state.dt_point_map=new TreeMap(); state.distance=0; ",
"map_script": "state.dt_point_map.put(doc.date.value,doc.pos.value);",
"combine_script": "int i=0;long prev=0; for(p in state.dt_point_map.values()){if(i==0){prev=p;i++;}else{state.distance+=Math.abs(p-prev);prev=p;i++;}} return state.distance;",
"reduce_script": "double overallDistance = 0; for (distance in states) { overallDistance += distance } return overallDistance;"
}
}
}
}
}
}
建议:预先计算并存储数据以便快速访问。
我有 'vehicles' 索引模式,每个文档都有一个车牌号 ('plateNo')、'position' 和 'date' 字段。作为测试,我想按车牌号对该索引中的所有文档进行分组,然后按日期对文档进行排序,最后计算每辆车移动的距离,并将每两个位置之间的绝对差相加。
例如:
plateNo | position | date |
---|---|---|
vehicle 1 | 1 | May 16, 2021 @ 15:55:37 |
vehicle 2 | 7 | May 16, 2021 @ 15:55:05 |
vehicle 1 | 5 | May 16, 2021 @ 15:54:30 |
vehicle 2 | 10 | May 16, 2021 @ 15:53:01 |
vehicle 1 | 2 | May 16, 2021 @ 15:50:41 |
的输出必须是
plateNo | distance |
---|---|
vehicle 1 | abs(5 - 2) + abs(1 - 5) = 7 |
vehicle 2 | abs(7 - 10) = 3 |
我如何使用 Painless 做到这一点? - 快速响应很重要,文档数量非常大 谢谢
假设:
- 同一车辆的数据存在于单个分片上
- 映射中定义的日期格式为'epoch_millis'
- 如果车辆只有一次进入,则其距离将为零
使用的聚合: scripted_metric
步骤:
- Init: 初始化了一个 TreeMap 用于存储 timestamp 作为 key 和 pos 作为 value
- Map: 将timestamp & pos的值放入TreeMap
- 收集:获取值并计算位置差(pos按时间戳排序返回)
- 减少: Return距离
示例查询:
GET vehicle/_search
{
"size": 0,
"aggs": {
"vehicles": {
"terms": {
"field": "vehicle",
"size": 10
},
"aggs": {
"distance": {
"scripted_metric": {
"init_script": "state.dt_point_map=new TreeMap(); state.distance=0; ",
"map_script": "state.dt_point_map.put(doc.date.value,doc.pos.value);",
"combine_script": "int i=0;long prev=0; for(p in state.dt_point_map.values()){if(i==0){prev=p;i++;}else{state.distance+=Math.abs(p-prev);prev=p;i++;}} return state.distance;",
"reduce_script": "double overallDistance = 0; for (distance in states) { overallDistance += distance } return overallDistance;"
}
}
}
}
}
}
建议:预先计算并存储数据以便快速访问。