我想在elasticsearch中使用存储桶来做与Haskell的zipWith相当的工作。
我有一个带有时间和值的索引" tuples ",每个条目也有一个head_id
,指向关于一系列这样的元组的元信息。这是timeseries ID。可视化后可能如下所示:
head_id | timestamp | value
---------+---------------+-------
1 | 1104537600000 | 10
1 | 1104538500000 | 20
1 | 1104539400000 | 30
2 | 1104537600000 | 1000
2 | 1104538500000 | 2000
2 | 1104539400000 | 3000
为了清楚起见,让我们将每个单独的时间序列表示为如下列表:
1: [ 10, 20, 30]
2: [1000, 2000, 3000]
我想要实现的是将这些序列“压缩”到一个elasticsearch聚合中:比方说,我想对它们进行sum
:
result: [1010, 2020, 3030]
我目前需要获取所有数据,并在应用程序代码中执行所需的操作。现在,为了节省内存和网络带宽,我想直接在elasticsearch中执行一些类似这样的操作。
在本例中,因为我想要添加的值共享相同的时间戳,所以我能够使用带有sum
子聚合的terms
存储桶聚合来实现这一点
GET /timeseries/_search
{
"aggs": {
"result": {
"terms": {"field": "timestamp"},
"aggs": {
"values_sum": {
"sum": {"field": "value"}
}
}
}
}
}
返回(简化):
{
"aggregations": {
"result": {
"buckets": [
{
"key": 1104537600000,
"doc_count": 2,
"values_sum": {"value": 1010}
},
{
"key": 1104538500000,
"doc_count": 2,
"values_sum": {"value": 2020}
},
{
"key": 1104539400000,
"doc_count": 2,
"values_sum": {"value": 3030}
}
]
}
}
}
然而,在我的例子中,不能保证时间序列的时间戳会像这样对齐,这意味着我需要一种更通用的方法来聚合2个(或更一般的N个)时间序列,假设它们每个都有相同数量的值。
我想到的一个可能的解决方法是将每个时间序列的开头移到0,然后使用上面的技术。然而,我不知道我如何才能做到这一点。
我想到的另一个可能的解决方法是首先在head_id
上聚合,为每个时间序列获取一个存储桶,然后使用类似serial differencing aggregation with lag=1
的东西。不过,我不能使用这种聚合,因为除了减法之外,我还想做其他操作,而且它需要通过histogram
聚合来生成存储桶,这对我来说不是这样的。
发布于 2017-05-12 14:57:12
我想到的一个可能的解决方法是将每个时间序列的开头移到0,然后使用上面的技术。然而,我不知道我如何才能做到这一点。
这可以使用terms
存储桶密钥的脚本来实现。它看起来是这样的:
GET /timeseries/_search
{
"aggs": {
"result": {
"terms": {
"field": "timestamp",
"script": {
"inline": "_value - params.anchors[doc.head_id.value]",
"params": {
"anchors": {
"1": 1104537600000,
"2": 1104624000000,
...
}
}
}
},
"aggs": {
"values_sum": {
"sum": {"field": "value"}
}
}
}
}
}
其中,anchors
是将head_id
与每个序列应开始的相应时刻相关联的映射。
https://stackoverflow.com/questions/43914895
复制