使用组对聚合进行分区

时间:2017-04-12 12:56:05

标签: elasticsearch aggregate partitioning

我正在尝试在ElasticSearch文档中对类似于the example的聚合进行分区,但是我没有让这个示例工作。

索引填充了事件类型:

public class Event
{
    public int EventId { get; set; }
    public string SegmentId { get; set; }
    public DateTime Timestamp { get; set; }
}

EventId是唯一的,每个事件都属于特定的SegmentId。每个SegmentId可以与零到多个事件相关联。

问题是: 如何获取每个EventId的最新SegmentId

我希望独特片段的数量在1000万的范围内,并且独特事件的数量会增加一个或两个。这就是为什么我认为使用top_hits本身并不恰当,suggested here。因此,分区。

示例:

我已经设置了一个填充了1313个文档(唯一EventId)的演示索引,属于101个不同的SegmentId(即每个段13个事件)。我希望下面的查询能够正常工作,但无论我指定的是哪个partition,都会返回完全相同的结果。

POST /demo/_search
{
  "size": 0,
  "aggs": {
    "segments": {
      "terms": {
        "field": "segmentId",
        "size": 15,                  <-- I want 15 segments from each query
        "include": {
          "partition": 0,            <-- Trying to retrieve the first partition
          "num_partitions": 7        <-- Expecting 7 partitions (7*15 > 101 segments)
        }
      },
      "aggs": {
        "latest": {
          "top_hits": {
            "size": 1,
            "_source": [
              "timestamp",
              "eventId",
              "segmentId"
            ],
            "sort": {
              "timestamp": "desc"
            }
          }
        }
      }
    }
  }
}

如果我删除include并将size设置为大于101的值,则会获得每个细分的最新事件。但是,我怀疑这是一个有百万桶的好方法......

2 个答案:

答案 0 :(得分:1)

您正在尝试进行聚合的Scroll

Scroll API仅支持搜索查询,不支持聚合。如果您不想使用Top Hits,正如您所说,由于文档数量众多,您可以尝试:

  1. Parent/Child方法 - 您将段创建为父文档和子文档中的事件。每次添加子项时,都可以更新父文档中的时间戳字段。通过这样做,您可以只查询父文档,您将获得您的段ID +最后一个事件时间戳

  2. 另一种方法是尝试仅在过去24小时内获得热门点击。因此,您可以添加查询,以便在过去24小时内首先过滤,然后尝试使用top_hit获取aggs。

答案 1 :(得分:0)

事实证明我正在调查错误的问题......我的例子确实很有效。

问题是我的本地ElasticSearch节点。我不知道它出了什么问题,但是当在另一台机器上重复这个例子时,它起作用了。但是,我无法在当前的ES安装上进行分区工作。因此,我再次卸载并重新安装了ElasticSearch,然后该示例正常工作。

要回答我原来的问题,我提供的示例是要走的路。我通过使用cardinality aggregate来估算产品总数来解决我的问题,从中我得出了合适数量的分区。然后我为每个分区循环上面的查询,并将文档添加到最终列表中。