在弹性搜索中,先按一个字段聚合,然后按两个字段使用日期范围聚合



我有这个类型的实体保存到elasticSearch:

class Value {

private Integer priority;
private Date dueDate;

}

对于优先级,可能的值是1和2(我知道应该使用enum,但让我们不专注于此)。现在使用弹性搜索,我想得到以下结果:

  1. 今天或过去有多少优先级为1的值
  2. 我有多少优先级为1的值已dueDate为空或将来
  3. 有多少优先级为2的值在今天或过去到期
  4. 我有多少优先级为2的值已dueDate为空或将来

我试着做的是:

SearchRequest request = new SearchRequest.Builder()
.index(MY_INDEX)
.query(getQuery(someKeys))
.aggregations(ELASTIC_AGG_PRIORITY, Aggregation.of(a ->
a.terms(terms -> terms.field(ELASTIC_AGG_PRIORITY).missing(""))))
.build();

这将获得按优先级分组的聚合,并将知道优先级为1和优先级为2的值的数量。但我需要添加嵌套聚合,这是我的问题。如何将这些桶分开,我将其分为过去或今天的dueDate和未来或null的dueDate。此外,我在编写范围查询时遇到问题:

public static Query getRangeQuery(String field) {
return QueryBuilders.range().field(field).lte(JsonData.of(new Date())).build()._toQuery();
}

我不能通过的一年,我不知道如何处理空当我需要选择一切在未来和空值。我尝试了以下操作,但没有得到我需要的结果:

SearchRequest request = new SearchRequest.Builder()
.index(MY_INDEX)
.query(getQuery(someKeys))
.aggregations(ELASTIC_AGG_ASSIGNEE, Aggregation.of(a ->
a.terms(terms -> terms.field(ELASTIC_AGG_ASSIGNEE).missing(""))))
.aggregations(ELASTIC_AGG_PRIORITY, Aggregation.of(a ->
a.terms(terms -> terms.field(ELASTIC_AGG_PRIORITY).missing(""))
.aggregations(ELASTIC_AGG_PRIORITY, Aggregation.of(filterAgg -> filterAgg
.filter(QueryUtil.getRangeQuery("dueDate"))))
)
).build();

其中QueryUtil.getRangeQuery(为上述方法。

所以总结一下我的问题是如何得到上面提到的4个结果?

你很接近了,但是你需要实现"date_range_aggregation"得到你想要的结果。

您的术语聚合是ok的,您所需要做的就是将date_range_aggregation作为子聚合添加到术语聚合。

为您的"null"值,设置一个"缺失";作为过去的事物的价值。这样你就可以把它作为第三个桶。

样本(json):

{
"aggs": {
"range": {
"date_range": {
"field": "date",
"missing": "1976/11/30",
"ranges": [
{ 
"key": "Oldest",
"to" : "1976/11/30"
},
{
"key": "Past",
"from" : "1976/11/30"
"to": "now"
}, 
{
"key": "Future",
"from": "now"
}
]
}
}
}
}

让我知道这是否适合你。

最新更新