解决 SpringBoot Elasticsearch 7.x 聚合查询遇到的问题
SpringBoot Elasticsearch 7.x 聚合查询遇到的问题
- 1. 时间的问题
- 2. 无法进行聚类的问题
- 2.1 解决
- 3. 类型转换的问题
- 4. QueryBuilders.termQuery() 查询无数据的问题
- 4.1 解决
1. 时间的问题
报错
java.time.DateTimeException: Unable to obtain Instant from TemporalAccessor: {},ISO resolved to 2019-04-30T16:00 of type java.time.format.Parsed
解决:
POJO 类中Date
类型转化为LocalDate
类型.
// 创建时间
@Field(type = FieldType.Date, format = DateFormat.date_hour_minute_second)
private LocalDate createTime;
// 更新时间
@Field(type = FieldType.Date, format = DateFormat.date_hour_minute_second)
private LocalDate updateTime;
如果还报错可以将
Date
类型转化为LocalDate
类型.
先试第一个再试第二个.
开始 Date 不好使, 之后我是试了 LocalDate 第二个不好使, 试第一个好使.
2. 无法进行聚类的问题
报错
org.springframework.data.elasticsearch.UncategorizedElasticsearchException: Elasticsearch exception [type=search_phase_execution_exception, reason=all shards failed]; nested exception is ElasticsearchStatusException[Elasticsearch exception [type=search_phase_execution_exception, reason=all shards failed]]; nested: ElasticsearchException[Elasticsearch exception [type=illegal_argument_exception, reason=Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [categoryName] in order to load field data by uninverting the inverted index. Note that this can use significant memory.]]; nested: ElasticsearchException[Elasticsearch exception [type=illegal_argument_exception, reason=Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [categoryName] in order to load field data by uninverting the inverted index. Note that this can use significant memory.]];
报错中有这样一句:
set fielddata=true on [categoryName]
2.1 解决
在 POJO 类中添加:
fielddata=true
@Field(type = FieldType.Keyword, fielddata=true)
private String categoryName;
上面添加了
FieldType.Keyword
不分词
用 Kibana 查看发现:不分词可以用categoryName.keyword
如果想让 categoryName 分词进行聚类:
需要添加:"fielddata": true
3. 类型转换的问题
报错
java.lang.ClassCastException: class org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms cannot be cast to class org.elasticsearch.search.aggregations.bucket.terms.StringTerms (org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms and org.elasticsearch.search.aggregations.bucket.terms.StringTerms are in unnamed module of loader 'app')
报错中是无法转化成
StringTerms
类型.
在之前的版本中是可以的, 但在 7 版本以上就不好使了.
需要将StringTerms
类型改为Terms
类型.
// 获取分组数据
Terms terms = Objects.requireNonNull(searchSkuInfo.getAggregations()).get(termsId);
4. QueryBuilders.termQuery() 查询无数据的问题
用 QueryBuilders.termQuery() 查询没有数据.
原因第一个可能是中文的缘故. 这时候可以用英文试一试. 需中文查询还需要解决.
原因第二个可能是含义没有弄清楚. QueryBuilders.termQuery() 精准匹配, 不进行分词, 也不是模糊匹配, 是完全匹配才可以好使. 而且只支持单个添加, 多个条件需要用 QueryBuilders.termsQuery().
原因第三个可能是 Java Rest Client 客户端自带的 bug.
4.1 解决
方法一:
可以将QueryBuilders.termQuery(name, value)
中的name
加上.keyword
.
方法二:
可以将QueryBuilders.termQuery()
直接用QueryBuilders.matchPhraseQuery()
代替.QueryBuilders.matchPhraseQuery()
也是进行精准匹配, match 查询是高级查询, 底层使用了 term 查询.