如何在Elasticsearch中按子汇总结果过滤匹配

时间:2018-11-12 03:03:46

标签: elasticsearch event-sourcing

我一直在实施一个以Elasticsearch为后盾的事件源解决方案。文档代表状态更改事件,由_source上的id字段链接。从sequence开始有一个0字段,因此每个id的最高序列是该id的最新事件。实际上,其他数据仅在第一个事件上可用,而后续事件将仅包含已更改的字段。目标是拥有一个索引,我永远不必向其发送更新,只需插入。

仅当其最新事件的statusREADY匹配时,尝试创建一个查询,该查询将返回按其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是为了使此查询可以按计划的批次运行,请始终抓取结果的顶部并更新链,以使它们不会出现在下一个查询中。

1 个答案:

答案 0 :(得分:1)

我对此进行了深入研究,并试图对其进行研究。我认为这归结为各个集合的局限性。无法对top_hits进行子汇总,因此我需要其他方法来过滤返回的结果。

我最终发现有人在做类似的事情:https://rahulsinghai.blogspot.com/2016/07/elasticsearch-pipeline-bucket-selector.html

输入合并top_hitsmax到每个max的{​​{1}}序列和id聚合的同一级别,然后再输入另一个{{1} }在filter聚合上进行聚合,以仅针对状态为max的每个结果,按filter每一个max找到id序列,假设所有共享一个id的事件都至少有一个事件处于READY状态,然后使用READY聚合根据bucket_selectormax结果选择相关集合。

可能的解决方案:

filter