Java Unix 时间戳的范围聚合
Java Range Aggregation over Unix timestamps
在我们的 elasticsearch(2.3.1 版)索引中,每个文档都有一个 showDate
字段。该字段包含一个 unix 时间戳,我想找出在过去 24 小时内有多少文档具有 showDate
以及在过去 7 天内有多少文档具有 showDate
。
在我的 Java 代码中,这是我尝试完成此操作的方式:
public static final String TODAY = "today";
public static final String THIS_WEEK = "thisWeek";
protected static final int SECONDS_PER_DAY = (24 * 60 * 60);
//...
Date now = new Date();
double timestampNow = now.getTime() / 1000;
double timestampYesterday = timestampNow - SECONDS_PER_DAY;
double timestampThisWeek = timestampNow - (SECONDS_PER_DAY * 7);
AbstractAggregationBuilder aggregation = AggregationBuilders.range("time").field("showDate")
.addRange(TODAY, timestampYesterday, timestampNow)
.addRange(THIS_WEEK, timestampThisWeek, timestampNow);
searchRequestBuilder.addAggregation(aggregation);
当我执行这个搜索请求并查看生成的查询时,我得到类似这样的结果
{
"from": 0,
"size": 15,
"query": {
...
}
"aggregations": {
"time": {
"range": {
"field": "showDate",
"ranges": [
{
"key": "today",
"from": 1.465369290E9,
"to": 1.465455690E9
},
{
"key": "thisWeek",
"from": 1.464850890E9,
"to": 1.465455690E9
}
]
}
}
}
}
当我在 Kopf or Head 等插件中执行查询时,我得到了预期的结果。当我在 java 服务中执行它时,docCount 始终为 0。
我注意到的唯一区别是插件将 double 值转换为 long 值。所以在我发送查询后 1.465455690E9
数字被转换为 1465455690
。有谁知道我如何在 Java 服务中获得与插件相同的结果?
更新 1
感谢 Dimitris 的回答,我的代码看起来像这样。但是它仍然没有给出预期的结果。 DocCount 仍然始终为 0,即使 Head 和 Kopf 告诉我有结果。
Date now = new Date();
long timestampNow = now.getTime() / 1000;
long timestampYesterday = timestampNow - SECONDS_PER_DAY;
long timestampThisWeek = timestampNow - (SECONDS_PER_DAY * 7);
AbstractAggregationBuilder aggregation = AggregationBuilders.dateRange(KEY).field("showDate").format("epoch_second")
.addRange(TODAY, timestampYesterday, timestampNow)
.addRange(THIS_WEEK, timestampThisWeek, timestampNow);
更新二:
我的最终解决方案如下所示:
Date now = new Date();
long timestampNow = now.getTime() / 1000;
long timestampYesterday = timestampNow - SECONDS_PER_DAY;
long timestampThisWeek = timestampNow - (SECONDS_PER_DAY * 7);
AbstractAggregationBuilder aggregation = AggregationBuilders.dateRange(KEY).field("showDate").format("epoch_second")
.addRange(TODAY, String.valueOf(timestampYesterday), String.valueOf(timestampNow))
.addRange(THIS_WEEK, String.valueOf(timestampThisWeek), String.valueOf(timestampNow))
我还必须更改我的索引,以便 showDate
是日期类型(格式仍然是 epoch_second)。
改用AggregationBuilders.dateRange。
在你的例子中:
...
AbstractAggregationBuilder aggregation = AggregationBuilders.dateRange("time").field("showData").format("epoch_second")
.addRange(TODAY, (long) timestampYesterday, (long) timestampNow)
.addRange(THIS_WEEK, (long) timestampThisWeek, (long) timestampNow);
请注意,您需要设置设置日期的格式,在您的情况下 "epoch_second" 对应的 elasticsearch 内置格式(参见:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#built-in-date-formats)
更新
原来时间戳必须作为字符串传入。因此代码变为:
...
AbstractAggregationBuilder aggregation = AggregationBuilders.dateRange("time").field("showData").format("epoch_second")
.addRange(TODAY, String.valueOf(timestampYesterday), String.valueOf(timestampNow))
.addRange(THIS_WEEK, String.valueOf(timestampThisWeek), String.valueOf(timestampNow));
在我们的 elasticsearch(2.3.1 版)索引中,每个文档都有一个 showDate
字段。该字段包含一个 unix 时间戳,我想找出在过去 24 小时内有多少文档具有 showDate
以及在过去 7 天内有多少文档具有 showDate
。
在我的 Java 代码中,这是我尝试完成此操作的方式:
public static final String TODAY = "today";
public static final String THIS_WEEK = "thisWeek";
protected static final int SECONDS_PER_DAY = (24 * 60 * 60);
//...
Date now = new Date();
double timestampNow = now.getTime() / 1000;
double timestampYesterday = timestampNow - SECONDS_PER_DAY;
double timestampThisWeek = timestampNow - (SECONDS_PER_DAY * 7);
AbstractAggregationBuilder aggregation = AggregationBuilders.range("time").field("showDate")
.addRange(TODAY, timestampYesterday, timestampNow)
.addRange(THIS_WEEK, timestampThisWeek, timestampNow);
searchRequestBuilder.addAggregation(aggregation);
当我执行这个搜索请求并查看生成的查询时,我得到类似这样的结果
{
"from": 0,
"size": 15,
"query": {
...
}
"aggregations": {
"time": {
"range": {
"field": "showDate",
"ranges": [
{
"key": "today",
"from": 1.465369290E9,
"to": 1.465455690E9
},
{
"key": "thisWeek",
"from": 1.464850890E9,
"to": 1.465455690E9
}
]
}
}
}
}
当我在 Kopf or Head 等插件中执行查询时,我得到了预期的结果。当我在 java 服务中执行它时,docCount 始终为 0。
我注意到的唯一区别是插件将 double 值转换为 long 值。所以在我发送查询后 1.465455690E9
数字被转换为 1465455690
。有谁知道我如何在 Java 服务中获得与插件相同的结果?
更新 1 感谢 Dimitris 的回答,我的代码看起来像这样。但是它仍然没有给出预期的结果。 DocCount 仍然始终为 0,即使 Head 和 Kopf 告诉我有结果。
Date now = new Date();
long timestampNow = now.getTime() / 1000;
long timestampYesterday = timestampNow - SECONDS_PER_DAY;
long timestampThisWeek = timestampNow - (SECONDS_PER_DAY * 7);
AbstractAggregationBuilder aggregation = AggregationBuilders.dateRange(KEY).field("showDate").format("epoch_second")
.addRange(TODAY, timestampYesterday, timestampNow)
.addRange(THIS_WEEK, timestampThisWeek, timestampNow);
更新二: 我的最终解决方案如下所示:
Date now = new Date();
long timestampNow = now.getTime() / 1000;
long timestampYesterday = timestampNow - SECONDS_PER_DAY;
long timestampThisWeek = timestampNow - (SECONDS_PER_DAY * 7);
AbstractAggregationBuilder aggregation = AggregationBuilders.dateRange(KEY).field("showDate").format("epoch_second")
.addRange(TODAY, String.valueOf(timestampYesterday), String.valueOf(timestampNow))
.addRange(THIS_WEEK, String.valueOf(timestampThisWeek), String.valueOf(timestampNow))
我还必须更改我的索引,以便 showDate
是日期类型(格式仍然是 epoch_second)。
改用AggregationBuilders.dateRange。
在你的例子中:
...
AbstractAggregationBuilder aggregation = AggregationBuilders.dateRange("time").field("showData").format("epoch_second")
.addRange(TODAY, (long) timestampYesterday, (long) timestampNow)
.addRange(THIS_WEEK, (long) timestampThisWeek, (long) timestampNow);
请注意,您需要设置设置日期的格式,在您的情况下 "epoch_second" 对应的 elasticsearch 内置格式(参见:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#built-in-date-formats)
更新
原来时间戳必须作为字符串传入。因此代码变为:
...
AbstractAggregationBuilder aggregation = AggregationBuilders.dateRange("time").field("showData").format("epoch_second")
.addRange(TODAY, String.valueOf(timestampYesterday), String.valueOf(timestampNow))
.addRange(THIS_WEEK, String.valueOf(timestampThisWeek), String.valueOf(timestampNow));