【发布时间】:2018-10-02 16:19:22
【问题描述】:
在 Elasticsearch 中,我将项目状态快照存储在仅附加方案中。 例如:
POST /item/item
{
"id": "1",
"time": "2018-09-19T00:00:00Z",
status": "ON_HOLD"
}
POST /item/item
{
"id": "2",
"time": "2018-09-19T00:01:00Z",
"status": "ON_HOLD"
}
POST /item/item
{
"id": "2",
"time": "2018-09-19T00:02:00Z",
"status": "DONE"
}
现在,我希望回答以下问题:哪些项目仍处于保留状态? (status==ON_HOLD)。
在这个简单的例子中,答案是:
{
"id": "1",
"time": "2018-09-19T00:00:00Z",
status": "ON_HOLD"
}
所以,为了获得项目的最后状态,我在id 上使用术语聚合,如下所示:
GET /item/_search
{
"size": 0,
"query": {
"match_all": {}
},
"aggs": {
"id": {
"terms": {
"field": "id.keyword",
"size": 10
},
"aggs": {
"top_items": {
"top_hits": {
"size": 1,
"sort": [
{
"time": {
"order": "desc"
}
}
],
"_source": {
"includes": ["*"]
}
}
}
}
}
}
}
这为我提供了由其 id 标识的每个项目的最后可用状态:
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 0,
"hits": []
},
"aggregations": {
"id": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "2",
"doc_count": 2,
"top_items": {
"hits": {
"total": 2,
"max_score": null,
"hits": [
{
"_index": "item",
"_type": "item",
"_id": "S-5eCGYBNyILygyml2jR",
"_score": null,
"_source": {
"id": "2",
"time": "2018-09-19T00:02:00Z",
"status": "DONE"
},
"sort": [
1537315320000
]
}
]
}
}
},
{
"key": "1",
"doc_count": 1,
"top_items": {
"hits": {
"total": 1,
"max_score": null,
"hits": [
{
"_index": "item",
"_type": "item",
"_id": "Se5eCGYBNyILygymjmg0",
"_score": null,
"_source": {
"id": "1",
"time": "2018-09-19T00:00:00Z",
"status": "ON_HOLD"
},
"sort": [
1537315200000
]
}
]
}
}
}
]
}
}
}
现在的问题是我想在 Elasticsearch 端(而不是客户端)过滤结果(聚合后)。
我尝试了 bucket_selector 聚合,但由于 top_hits 结果不是数字或单值数字聚合,所以它报错了。
我还尝试添加一个 script_field 来获取数值,但之后似乎无法使用:
"script_fields": {
"on_hold": {
"script": {
"lang": "painless",
"source": "doc['status.keyword'].value == 'ON_HOLD' ? 1 : 0"
}
}
}
我想要在 Elasticsearch 端做的事情是否可行,还是我必须在客户端做?
PS:在聚合之前添加过滤器不会提供正确的结果,因为它会返回在任何时间点都为ON_HOLD 的项目。
编辑: 好的,我正在到达某个地方:
GET /item/_search
{
"size": 0,
"query": {
"match_all": {}
},
"aggs": {
"id": {
"terms": {
"field": "id.keyword",
"size": 50
},
"aggs": {
"top_item": {
"terms": {
"size": 1,
"field": "time",
"order": {
"_key": "desc"
}
},
"aggs": {
"on_hold": {
"filter": {
"term": {
"status.keyword": "ON_HOLD"
}
},
"aggs": {
"document": {
"top_hits": {
"size": 1,
"_source": ["*"]
}
}
}
}
}
}
}
}
}
}
top_hits 聚合是一个指标,而不是桶聚合,所以它不做这项工作,必须最后使用。
最后一个问题:过滤掉的桶会留下空叶子: “命中”:[]
有没有办法从结果树中删除以空叶子结尾的分支?谢谢
【问题讨论】:
-
看你的例子,项目 2 必须处于“DONE”状态而不是“ON_HOLD”,对吧?
-
是的,第 2 项的状态为“DONE”,必须过滤掉
标签: elasticsearch elasticsearch-aggregation