Unix时间戳上的Java范围聚合

时间:2016-06-09 08:52:02

标签: java elasticsearch aggregation elasticsearch-aggregation

在我们的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
          }
        ]
      }
    }
  }
}

当我在KopfHead等插件中执行查询时,我得到了预期的结果。当我在我的java服务中执行它时,docCount始终为0.

我注意到的唯一区别是插件将double值转换为long值。因此,在我发送查询后,1.465455690E9号码将转换为1465455690。有谁知道我在Java服务中获得的结果与从插件中得到的结果相同?

更新1 感谢Dimitris的回答,我的代码看起来像这样。但是它仍然没有给出预期的结果。即使Head和Kopf告诉我有结果,DocCount仍然是0。

    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);

更新2: 我的最终解决方案如下:

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的类型为date(格式仍为epoch_second)。

1 个答案:

答案 0 :(得分:1)

请改用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);

请注意,您需要设置日期设置的格式,对于相应的elasticsearch内置格式,请设置“epoch_second”(请参阅​​: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));