我一直在实施一个以Elasticsearch为后盾的事件源解决方案。文档代表状态更改事件,由_source上的id
字段链接。从sequence
开始有一个0
字段,因此每个id
的最高序列是该id
的最新事件。实际上,其他数据仅在第一个事件上可用,而后续事件将仅包含已更改的字段。目标是拥有一个索引,我永远不必向其发送更新,只需插入。
仅当其最新事件的status
与READY
匹配时,尝试创建一个查询,该查询将返回按其ID分组的第一个和最后一个事件。
样本数据:
[
{
"_index":"events",
"_type":"event",
"_id":"AWcFf2N-IqNGd75vWMgc",
"_score":1,
"_source":{
"id":"event_chain-1",
"status":"SENT",
"sequence":1,
"timestamp":"1541985493824",
"export_batch_id":"103709fe-959f-4b4e-8255-ef59f18a3cf6"
}
},
{
"_index":"events",
"_type":"event",
"_id":"AWbQomwoIqNGd75vWMf6",
"_score":1,
"_source":{
"id":"event_chain-1",
"status":"READY",
"sequence":"0",
"timestamp":"2018-10-31T00:00:00Z"
}
},
{
"_index":"events",
"_type":"event",
"_id":"AWbQomwoIqNGd75vWabc",
"_score":1,
"_source":{
"id":"event_chain-2",
"status":"READY",
"sequence":"0",
"timestamp":"2018-10-31T00:00:00Z"
}
}
]
我在id.keyword字段上写了一个术语聚合,并在两个top_hits子聚合上分别通过按顺序排序并分别获取顶部和底部结果来获取第一事件和最新事件。
问题是我对状态进行的任何匹配都发生在聚合之前,并且我需要一种方法来从术语聚合结果中排除任何last_event的状态与READY
不匹配的匹配。 / p>
到目前为止我所拥有的:
POST /events/_search
{
"size": 0,
"query": {
"bool": {
"must": {
"match": {
"status": "READY"
}
}
}
},
"aggs": {
"group_by_id": {
"terms": {
"field": "id.keyword",
"order": {
"_term": "asc"
},
"size": 100
},
"aggs": {
"latest_event": {
"top_hits": {
"sort": [
{
"sequence": {
"order": "desc"
}
}
],
"from": 0,
"size": 1
}
},
"first_event": {
"top_hits": {
"sort": [
{
"sequence": {
"order": "asc"
}
}
],
"from": 0,
"size": 1
}
}
}
},
"num_ready": {
"cardinality": {
"field": "id.keyword"
}
}
}
}
这将返回两个术语,一个用于event_chain-1
,另一个用于event_chain-2
,当我只希望一个用于event_chain-2
时
术语agg size
是为了使此查询可以按计划的批次运行,请始终抓取结果的顶部并更新链,以使它们不会出现在下一个查询中。
答案 0 :(得分:1)
我对此进行了深入研究,并试图对其进行研究。我认为这归结为各个集合的局限性。无法对top_hits
进行子汇总,因此我需要其他方法来过滤返回的结果。
我最终发现有人在做类似的事情:https://rahulsinghai.blogspot.com/2016/07/elasticsearch-pipeline-bucket-selector.html
输入合并top_hits
,max
到每个max
的{{1}}序列和id
聚合的同一级别,然后再输入另一个{{1} }在filter
聚合上进行聚合,以仅针对状态为max
的每个结果,按filter
每一个max
找到id
序列,假设所有共享一个id的事件都至少有一个事件处于READY
状态,然后使用READY
聚合根据bucket_selector
和max
结果选择相关集合。
可能的解决方案:
filter