我正在尝试在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的值,则会获得每个细分的最新事件。但是,我怀疑这是一个有百万桶的好方法......
答案 0 :(得分:1)
您正在尝试进行聚合的Scroll。
Scroll API仅支持搜索查询,不支持聚合。如果您不想使用Top Hits,正如您所说,由于文档数量众多,您可以尝试:
Parent/Child方法 - 您将段创建为父文档和子文档中的事件。每次添加子项时,都可以更新父文档中的时间戳字段。通过这样做,您可以只查询父文档,您将获得您的段ID +最后一个事件时间戳
另一种方法是尝试仅在过去24小时内获得热门点击。因此,您可以添加查询,以便在过去24小时内首先过滤,然后尝试使用top_hit获取aggs。
答案 1 :(得分:0)
事实证明我正在调查错误的问题......我的例子确实很有效。
问题是我的本地ElasticSearch节点。我不知道它出了什么问题,但是当在另一台机器上重复这个例子时,它起作用了。但是,我无法在当前的ES安装上进行分区工作。因此,我再次卸载并重新安装了ElasticSearch,然后该示例正常工作。
要回答我原来的问题,我提供的示例是要走的路。我通过使用cardinality aggregate来估算产品总数来解决我的问题,从中我得出了合适数量的分区。然后我为每个分区循环上面的查询,并将文档添加到最终列表中。