【发布时间】:2018-11-13 03:17:38
【问题描述】:
我一直在实施基于 elasticsearch 的事件溯源解决方案。文档代表状态变化事件,由_source 上的id 字段链接。有一个从0 开始的sequence 字段,因此每个id 的最高序列是该id 的最新事件。在实践中,附加数据将仅在第一个事件中可用,后续事件将仅包含已更改的字段。目标是拥有一个我永远不必向其发送更新的索引,只需插入。
尝试创建一个查询,该查询将返回按其 ID 分组的第一个和最后一个事件,前提是仅当其最新事件的 status 与 READY 匹配时。
样本数据:
[
{
"_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 字段上编写了一个 terms 聚合,以及两个 top_hits 子聚合,通过对序列进行排序并分别抓取顶部和底部的结果来获取第一个和最新的事件。
问题是我对状态所做的任何匹配都发生在聚合之前,我需要一种方法从术语聚合结果中排除所有最新事件的状态与READY 不匹配的匹配。
到目前为止我所拥有的:
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
Terms agg size 是这样的,所以这个查询可以在预定的批次中运行,总是抓取结果的顶部并更新链,这样它们就不会出现在下一个查询中。
【问题讨论】:
-
与 Elasticsearch 无关,但我的应用程序每个聚合的事件数通常少于 100,因此我们只需将它们全部加载并随后过滤。
-
这个写的很重,按计划阅读,所以我们的批次必须是可调整的并且在数据方面相当小(这使得查询后的过滤可能难以实现,因为没有 garauntee 你会如果过滤和未过滤的总和大于批量大小,则获得每批次的任何预期命中)。
标签: elasticsearch event-sourcing