使用组对聚合进行分区
Partitioning aggregates with groups
我正在尝试对类似于 ElasticSearch 文档中的 the example 的聚合进行分区,但我没有让示例正常工作。
索引中填充了事件类型:
public class Event
{
public int EventId { get; set; }
public string SegmentId { get; set; }
public DateTime Timestamp { get; set; }
}
EventId
是唯一的,每个事件都属于特定的SegmentId
。每个 SegmentId 都可以与零到多个事件相关联。
问题是:
如何为每个 SegmentId
获取最新的 EventId
?
我预计唯一细分市场的数量在 1000 万个范围内,而唯一事件的数量要大一到两个数量级。这就是为什么我不认为单独使用 top_hits
是合适的,如 。因此,分区。
示例:
我已经建立了一个包含 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 的值,我将获得每个分段的最新事件。但是,我怀疑这是一个百万桶的好方法......
您正在尝试进行 Scroll 聚合。
Scroll API 仅支持搜索查询,不支持聚合。如果您不想使用 Top Hits,如您所说,由于文档数量巨大,您可以尝试:
Parent/Child 方法 - 在其中创建段作为父文档和子文档中的事件。每次添加子文档时,您都可以更新父文档中的时间戳字段。通过这样做,您可以只查询父文档,您将获得您的段 ID + 最后一个事件时间戳
另一种方法是尝试仅在过去 24 小时内获得最高点击率。因此,您可以添加一个查询以首先过滤过去 24 小时,然后尝试使用 top_hit.
获取聚合
原来我调查错了问题...我的例子实际上很完美。
问题出在我的本地 ElasticSearch 节点上。我不知道它出了什么问题,但是在另一台机器上重复这个例子时,它起作用了。但是,我无法在我当前的 ES 安装上进行分区。因此,我再次卸载并重新安装了 ElasticSearch,然后该示例成功了。
回答我原来的问题,我提供的例子就是要走的路。我通过使用 cardinality aggregate 来估计产品总数解决了我的问题,我从中得出了合适的分区数。然后我为每个分区循环上面的查询,并将文档添加到最终列表。
我正在尝试对类似于 ElasticSearch 文档中的 the example 的聚合进行分区,但我没有让示例正常工作。
索引中填充了事件类型:
public class Event
{
public int EventId { get; set; }
public string SegmentId { get; set; }
public DateTime Timestamp { get; set; }
}
EventId
是唯一的,每个事件都属于特定的SegmentId
。每个 SegmentId 都可以与零到多个事件相关联。
问题是:
如何为每个 SegmentId
获取最新的 EventId
?
我预计唯一细分市场的数量在 1000 万个范围内,而唯一事件的数量要大一到两个数量级。这就是为什么我不认为单独使用 top_hits
是合适的,如
示例:
我已经建立了一个包含 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 的值,我将获得每个分段的最新事件。但是,我怀疑这是一个百万桶的好方法......
您正在尝试进行 Scroll 聚合。
Scroll API 仅支持搜索查询,不支持聚合。如果您不想使用 Top Hits,如您所说,由于文档数量巨大,您可以尝试:
Parent/Child 方法 - 在其中创建段作为父文档和子文档中的事件。每次添加子文档时,您都可以更新父文档中的时间戳字段。通过这样做,您可以只查询父文档,您将获得您的段 ID + 最后一个事件时间戳
另一种方法是尝试仅在过去 24 小时内获得最高点击率。因此,您可以添加一个查询以首先过滤过去 24 小时,然后尝试使用 top_hit.
获取聚合
原来我调查错了问题...我的例子实际上很完美。
问题出在我的本地 ElasticSearch 节点上。我不知道它出了什么问题,但是在另一台机器上重复这个例子时,它起作用了。但是,我无法在我当前的 ES 安装上进行分区。因此,我再次卸载并重新安装了 ElasticSearch,然后该示例成功了。
回答我原来的问题,我提供的例子就是要走的路。我通过使用 cardinality aggregate 来估计产品总数解决了我的问题,我从中得出了合适的分区数。然后我为每个分区循环上面的查询,并将文档添加到最终列表。