前言

我前一段时间,升级了公司的ES的版本,目前kibana使用的版本是8.5.0。

这两天遇到一个Date类型字段作为查询条件无法选择时间的问题,分享给大家,希望对你会有所帮助。

案发现场

有一天,某位同事通过xxx-log的index索引,在kibana后台通过搜索日志。

他搜索了某个关键字:Action,但是查出的日志太多了。

于是,他想通过时间范围查询。

在日志实体中,有个startTime字段,表示开始时间,正常情况下,在kibana后台是可以通过时间范围搜索日志的。

但现在却没法按时间过滤日志:image这到底是怎么回事呢?

分析原因

我查看了一下该index在ES中的字段类型,发现了一个很奇怪的问题:startTime的类型竟然是Long,而不是Date。

因为当时在java代码中定义的实体ThirdLogModel中的startTime类型是这样定义的:

private Date startTime;

明明定义的是Date类型,在ES中自动创建了索引之后,怎么会变成Long类型呢?

当时代码大概是这样的:

try {
   BulkRequest bulkRequest = new BulkRequest();
   IndexRequest indexRequest = new IndexRequest(index);
   indexRequest.source(JSON.toJSONString(logModel),XContentType.JSON);
   bulkRequest.add(indexRequest);
   BulkResponse response = esClient.bulk(bulkRequest, RequestOptions.DEFAULT);
   if(response.hasFailures()) {
     log.error("日志写入失败",e); 
   } else {
      log.info("日志写入成功");
   }
} catch(Throwable e) {
  log.error("日志写入失败",e); 
}

一眼看不出问题。

我上网搜索了一下。

网上说要在时间类型的字段上,用@JsonFormat注解转换一下格式,否则保存到ES中的时间格式是Long。

解决问题

我按照网上的说法在实际格式上加了@JsonFormat注解,代码改成这样的:

@JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone="GMT+8")
private Date startTime;

本以为可以一次性成功。

但是这样调整之后,发现还是没有生效,查看index中的startTime字段的数据类型,任然是Long类型。

我刚开始是以为是有缓存,于是在kibana后台手动删除了xxx-log这个index。

然后触发了自动生成index的业务逻辑,在ES中重新生成了xxx-log这个index。

于是,再次查看了一些index中的startTime字段的数据类型,任然是Long类型。

我去。。。这是什么情况?

我再回去查看了一下之前创建index的代码,发现了一个疑点:

indexRequest.source(JSON.toJSONString(logModel),XContentType.JSON);

这个方法的作用是将logModel实体,转换成json对象,然后赋值给source字段。

这个JSON.toJSONString方法用的是fastjson包下的方法。

而我们使用的@JsonFormat注解是jackson包下的注解。

原来如此,找到原因了,这不是牛头不对马嘴?

于是,我将之前其他同事写的JSON.toJSONString方法,改成使用jackson包下的ObjectMapper类去将实体转换成json字符串。

private static ObjectMapper objectMapper = new ObjectMapper();

indexRequest.source(objectMapper.writeValueAsString(logModel),XContentType.JSON);

这样调整之后,为了确保万无一失,再将之前的index删除了。

再次触发了业务功能,写入了新的日志到xxx-log这个index当中,它自动创建了这个index。

查看了一下startTime字段,类型已经变成了Date类型了。

已经解决问题了。

后续

通过前面的调整,已经将ES中startTime字段的数据类型改成了Date类型了。

但在kibana的discover页面,还是没办法根据startTime选择时间范围查询日志。

我查看了一下data view窗口,里面列出了我们所需要的一些index。

找出了我们用的那个index,删除掉了,重新创建了一个一样的。

果然,这样调整之后,在kibana的discover页面出现了时间搜索条件了。image成功解决问题了。

总结

通过这次解决ES时间问题的过程,我踩过了下面三个坑:

  1. 在创建ES的index时,对于Date类型字段,需要在代码中特殊处理一下,否则会自动变成Long类型。
  2. 使用@JsonFormat注解时,务必要使用jackson包下的json转换工具,否则该注解会失效。
  3. kibana页面的data view窗口,有缓存,有些功能调整了,没法实时生效。
最后修改:2026 年 06 月 06 日
如果觉得我的文章对你有用,请随意赞赏