计算数百万个相邻记录并在Elasticsearch中对它们进行汇总

时间:2018-04-20 13:28:07

标签: elasticsearch

我喜欢计算数百万条相邻记录,并在Elasticsearch中最后总结它们。我怎么能这样做?

Elasticsearch中的文档(其中六个)数据:

10
20
-30
10
30
100

计算:

  10  to  20 is  10
  20  to -30 is -50
 -30  to  10 is  40
  10  to  30 is  20
  30  to  100 is 70

总数是:

10 +( - 50)+ 40 + 20 + 70 = 90

如何使用REST进行查询 - RestHighLevelClient API来实现此目的?

1 个答案:

答案 0 :(得分:1)

通用案例

最有可能在Elasticsearch中执行此操作的唯一合理方法是denormalize并将已计算的增量放入Elasticsearch中。在这种情况下,您只需要一个简单的sum聚合。

这是因为Elasticsearch中的数据是" flat",因此它不知道您的文档是否相邻。当你需要知道的所有东西都已经在索引时已经存在于文档中时,它是擅长的:在这种情况下,特殊索引是预先构建的,聚合非常快。

就像A'tuin,来自Pratchett小说的平面版地球:一些基本物理,如来自RDBMS的JOIN,不起作用,但魔术是可能的。

时间序列特定案例

如果您有时间序列,可以结合使用Serial DifferencingSum Bucket sibling aggregations来实现目标。

为了使用这种方法,您需要在某个日期字段上进行聚合。想象一下,你有这样的映射:

PUT time_diff
{
  "mappings": {
    "doc": {
      "properties": {
        "eventTime": {
          "type": "date"
        },
        "val": {
          "type": "integer"
        }
      }
    }
  }
}

每天的文件如下:

POST /time_diff/doc/1
{
  "eventTime": "2018-01-01",
  "val": 10
}

POST /time_diff/doc/2
{
  "eventTime": "2018-01-02",
  "val": 20
}

然后使用这样的查询:

POST /time_diff/doc/_search
{
  "size": 0,
  "aggs": {
    "my_date_histo": {
      "date_histogram": {
        "field": "eventTime",
        "interval": "day"
      },
      "aggs": {
        "the_sum": {
          "sum": {
            "field": "val"
          }
        },
        "my_diff": {
          "serial_diff": {
            "buckets_path": "the_sum"
          }
        }
      }
    },
    "my_sum": {
      "sum_bucket": {
        "buckets_path": "my_date_histo>my_diff"
      }
    }
  }
}

响应如下:

{
  ...
  "aggregations": {
    "my_date_histo": {
      "buckets": [
        {
          "key_as_string": "2018-01-01T00:00:00.000Z",
          "key": 1514764800000,
          "doc_count": 1,
          "my_delta": {
            "value": 10
          }
        },
        ...
      ]
    },
    "my_sum": {
      "value": 90
    }
  }
}

这种方法有明显的局限性:

  • 仅在您有时间序列数据时才有效
  • 只有在每个日期存储桶中只有1个数据点(示例中为一天)时才会更正
  • 如果你有很多分数(如你所提到的数百万),
  • 会在内存消耗中爆炸。

希望有所帮助!