我的文档是这样的:
{'start': 0, 'stop': 3, 'val': 3}
{'start': 2, 'stop': 4, 'val': 1}
{'start': 5, 'stop': 6, 'val': 4}
我们可以想象,每个文档占据从'start'
到'stop'
的x坐标,并且具有一定的值'val'
('start' < 'stop'
是保证的)。
目标是绘制一条线,显示占据x坐标的所有文档中这些值'val'
的总和:
this graph online
在现实中,有许多文档具有许多不同的'start'
和'stop'
坐标。速度很重要,因此:
最多几个ElasticSearch请求就可以实现这一点吗?如何实现?
我尝试过的
通过一个ElasticSearch请求,我们可以得到min_start
和max_stop
坐标,这些将是x的边界。
然后,我们将x坐标划分为N
个区间,并在每个区间的循环中,我们发出一个ElasticSearch请求:以过滤掉完全位于该间隔之外的所有文档,并进行'val'
的总和聚合。
由于存在N+1
请求,因此这种方法花费的时间太多,如果我们希望得到精度更高的行,则时间将线性增加。
编码:
N = 300 # number of intervals along x
x = []
y = []
data = es.search(index='index_name',
body={
'aggs': {
'min_start': {'min': {'field': 'start'}},
'max_stop': {'max': {'field': 'stop'}}
}
})
min_x = data['aggregations']['min_start']['value']
max_x = data['aggregations']['max_stop']['value']
x_from = min_x
x_step = (max_x - min_x) / N
for _ in range(N):
x_to = x_from + x_step
data = es.search(
index='index_name',
body= {
'size': 0, # to not return any actual documents
'query': {
'bool': {
'should': [
# start is in the current x-interval:
{'bool': {'must': [
{'range': {'start': {'gte': x_from}}},
{'range': {'start': {'lte': x_to}}}
]}},
# stop is in the current x-interval:
{'bool': {'must': [
{'range': {'stop': {'gte': x_from}}},
{'range': {'stop': {'lte': x_to}}}
]}},
# current x-interval is inside start--stop
{'bool': {'must': [
{'range': {'start': {'lte': x_from}}},
{'range': {'stop': {'gte': x_to}}}
]}}
],
'minimum_should_match': 1 # at least 1 of these 3 conditions should match
}
},
'aggs': {
'vals_sum': {'sum': {'field': 'val'}}
}
}
)
# Append info to the lists:
x.append(x_from)
y.append(data['aggregations']['vals_sum']['value'])
# Next x-interval:
x_from = x_to
from matplotlib import pyplot as plt
plt.plot(x, y)
1条答案
按热度按时间vsdwdz231#
正确的方法是使用
range
field type(available since 5.2),而不是使用两个字段start
和stop
,然后重新实现相同的逻辑,如下所示:您的文档将如下所示:
然后,查询将简单地利用
histogram
聚合,如下所示:结果如预期:三三四一零四