【问题标题】:Elasticsearch NumberFormatException when running two consecutive java tests运行两个连续的 java 测试时出现 Elasticsearch NumberFormatException
【发布时间】:2015-06-15 14:16:42
【问题描述】:

我在一个班级有两个测试,每个测试都包含以下查询:

SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withFilter(rangeFilter("publishDate").lt(date)).build();

在其中一项测试中,结果的数量elasticsearchTemplate.count(searchQuery, Article.class),在另一项中验证返回值elasticsearchTemplate.queryForPage(searchQuery,Article.class)

如果我分别运行这两个测试中的任何一个,测试总是通过,一切似乎都运行良好。 如果我因此同时运行这两个测试,一个接一个,第一个通过,另一个失败,并出现 SearchPhaseExecutionException: Failed to execute phase 。 .. 嵌套:NumberFormatException[对于输入字符串:“2015-02-01T00:02:02.396Z”]...

更奇怪的是,这种行为仅在应用了发布日期的范围过滤器(具有类型:FieldType.Date)时出现。因此,当应用带有 boolFilter、termFilter 等的其他类似查询时,所有测试都通过了。

另外,如果我在同一个方法中运行这两个查询:不会引发异常。

我认为不正确的缓存初始化/清理可能会导致该行为...但是,为什么其他查询也没有发生?

另外,在类的@After 方法中,我删除了所有索引 (elasticsearchTemplate.deleteIndex(Article.class)),在 @Before 方法中,我执行/重做批量索引和刷新。

我走错路了吗?我在这里错过了什么?

完整的堆栈跟踪:

org.elasticsearch.action.search.SearchPhaseExecutionException: Failed to execute phase [dfs], all shards failed; shardFailures {[jCBsPj2yR3qkX6HxN_xr4w][articles][0]: SearchParseException[[articles][0]: query[ConstantScore(*:*)],from[0],size[10]: Parse Failure [Failed to parse source [{"from":0,"size":10,"query":{"match_all":{}},"post_filter":{"range":{"publishDate":{"from":null,"to":"2015-02-01T00:02:02.676Z","include_lower":true,"include_upper":false}}}}]]]; nested: NumberFormatException[For input string: "2015-02-01T00:02:02.676Z"]; }{[jCBsPj2yR3qkX6HxN_xr4w][articles][1]: SearchParseException[[articles][1]: query[ConstantScore(*:*)],from[0],size[10]: Parse Failure [Failed to parse source [{"from":0,"size":10,"query":{"match_all":{}},"post_filter":{"range":{"publishDate":{"from":null,"to":"2015-02-01T00:02:02.676Z","include_lower":true,"include_upper":false}}}}]]]; nested: NumberFormatException[For input string: "2015-02-01T00:02:02.676Z"]; }{[jCBsPj2yR3qkX6HxN_xr4w][articles][2]: SearchParseException[[articles][2]: query[ConstantScore(*:*)],from[0],size[10]: Parse Failure [Failed to parse source [{"from":0,"size":10,"query":{"match_all":{}},"post_filter":{"range":{"publishDate":{"from":null,"to":"2015-02-01T00:02:02.676Z","include_lower":true,"include_upper":false}}}}]]]; nested: NumberFormatException[For input string: "2015-02-01T00:02:02.676Z"]; }{[jCBsPj2yR3qkX6HxN_xr4w][articles][3]: SearchParseException[[articles][3]: query[ConstantScore(*:*)],from[0],size[10]: Parse Failure [Failed to parse source [{"from":0,"size":10,"query":{"match_all":{}},"post_filter":{"range":{"publishDate":{"from":null,"to":"2015-02-01T00:02:02.676Z","include_lower":true,"include_upper":false}}}}]]]; nested: NumberFormatException[For input string: "2015-02-01T00:02:02.676Z"]; }{[jCBsPj2yR3qkX6HxN_xr4w][articles][4]: SearchParseException[[articles][4]: query[ConstantScore(*:*)],from[0],size[10]: Parse Failure [Failed to parse source [{"from":0,"size":10,"query":{"match_all":{}},"post_filter":{"range":{"publishDate":{"from":null,"to":"2015-02-01T00:02:02.676Z","include_lower":true,"include_upper":false}}}}]]]; nested: NumberFormatException[For input string: "2015-02-01T00:02:02.676Z"]; }
at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction.onFirstPhaseResult(TransportSearchTypeAction.java:238)
at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction$1.onFailure(TransportSearchTypeAction.java:184)
at org.elasticsearch.search.action.SearchServiceTransportAction$23.run(SearchServiceTransportAction.java:565)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)

文章索引的映射:

@Document(indexName = "articles", type = "article", shards = 1, replicas = 0, refreshInterval = "-1", indexStoreType = "memory")
public class Article {
@Id
private Long id;
@Field(type = FieldType.String, store = true)
private String title;
@Field(type = FieldType.String, store = true)
private String text;
@Field(type = FieldType.String, store = true)
private String author;
@Field(type = FieldType.Date, store = true)
private Date publishDate;
@Field(type = FieldType.Date, store = true)
private Date lastModificationDate;
....
}

【问题讨论】:

  • publishDate 上构建rangeFilter() 时,date 变量在lt(date) 中来自哪里?它是一个可以在多个地方修改的全局变量吗?你能分享一些关于这方面的见解吗?
  • 我首先初始化日历实例,然后我就得到了calendar.getTime()。我在每个测试中都这样做。
  • 你能分享完整的堆栈跟踪吗?
  • 当然。我刚刚附上了它。
  • 能否也分享一下您的articles 索引的映射,好吗?看起来publishDatenumber 类型而不是date

标签: java date elasticsearch numberformatexception spring-data-elasticsearch


【解决方案1】:

由于异常抱怨NumberFormatException,您应该尝试将日期发送为long(而不是Date 对象),因为这是内部存储日期的方式。请参阅我在下面的代码中调用date.getTime()

SearchQuery searchQuery = new NativeSearchQueryBuilder()
    .withQuery(matchAllQuery())
    .withFilter(rangeFilter("publishDate").lt(date.getTime())).build();

【讨论】:

  • 是的,谢谢,这已经解决了问题。 :) 但是我还是不明白为什么每次单独运行时测试都通过了...
  • 这可能与 @After@Before 在两次测试运行之间的运行方式有关。可能是在第二次测试期间没有创建索引。
  • @Before 中,我创建了一些索引查询,我对elasticsearchTemplate.bulkIndex(queries) 进行批量索引,最后刷新(elasticsearchTemplate.refresh(Article.class, true))。在@After 我只是将它们全部删除(elasticsearchTemplate.deleteIndex(Article.class))。
【解决方案2】:

我也找到了其他解决方案。

@Before 方法中,我没有应用显式映射,这意味着不考虑来自Article 索引的@Field 注释。实际上,使用了默认映射。

通过添加显式映射:

elasticsearchTemplate.putMapping(Article.class)

publishDatetype 取自索引定义:

@Field(type = FieldType.Date, store = true)
private Date publishDate;

通过这种方式,所有测试都通过了,无论是单独运行它们还是按顺序运行它们。

此外,rangeFilter 参数也适用于初始 date type。 (当然,它也适用于 long type。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多