异常信息

核心提示在Please use a keyword field instead. Alternatively, set fielddata=true on [dataTimestamp] in order to load field data by uninverting the inverted index.
待排序字段dataTimestamp没有为排序优化,所以无法排序,需要配置FieldType.Keywordfielddata = true,可是代码中都配置了为什么还提示呢,往下看……

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 [dataTimestamp] 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 [dataTimestamp] in order to load field data by uninverting the inverted index. Note that this can use significant memory.]]

环境

spring-data-elasticsearch 4.1.3
ElasticSearch 7.9.3

<dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-elasticsearch</artifactId>
      <version>4.1.3</version>
</dependency>

spring-data-elasticsearch这块,对ElasticSearch 7.16之前的都差不多,相似版本可以尝试

代码配置

ElasticSearch实体

如下配置,异常提示需要将排序字段设置为Keyword类型(推荐),或者将fielddata设置为true(不推荐),可是我都设置了,还是提示上面的
注意:这里使用Spring ElasticSearch注解是否生效一定要注意,如果注解未生效就会导致声明的索引、字段信息都是无效的,所以配置了也没有,下面说如何检查

@Data
@Document(indexName = "test-index")
public class ElasticSearchEntity {
    /**
     * ElasticSearch Long型精度会丢失
     */
    @Id
    @Field(type = FieldType.Keyword)
    private String dataId;
    
    // 配置二选一即可,推荐FieldType.Keyword,使用fielddata = true相对更占资源
    @Field(type = FieldType.Keyword, fielddata = true)
    private String dataTimestamp;

}

检查ElasticSearch实体映射结果

项目启动后会自动在ElasticSearch创建索引,查询索引信息,有mapping才说明注解配置生效了,因为注解声明的字段信息在ElasticSearch对应的就是mapping
在这里插入图片描述
如果没有请检查,Java日志是否有如下类似的创建失败警告,按照警告提示修改实体注解配置,尝试至无警告创建,再到ElasticSearch查询索引是否正确加载mapping

[o.s.d.e.r.s.SimpleElasticsearchRepository,<init> : 96] - Cannot create index: Elasticsearch exception [type=mapper_parsing_exception, reason=Mapping definition for

ElasticSearch数据操作接口

public interface IndexRepository extends ElasticsearchRepository<ElasticSearchEntity, String> {
}

查询调用(高级查询接口自定义)

这里先列出来两种写法,因为mapping字段声明未加载成功可导致使用时的问题,推荐第一种,所以上面如果有问题的检查一下

Criteria criteria = new Criteria("title").contains(keyword);

// 1、没有加载mapping默认识别string类型,如果keyword声明加载成功这么写就可以了(推荐这种,所以上面如果有问题的检查一下)
Sort sort = Sort.by("_score", "dataTimestamp").descending();

// 2、没有加载mapping默认为string类型创建keyword,Keyword类型才有索引可以排序,想使用Keyword索引要加.keyword使用,否则还是原字段
Sort sort = Sort.by("_score", "dataTimestamp.keyword").descending();

Query query = new CriteriaQuery(criteria)
                .setPageable(
                        PageRequest.of(pageNum, pageSize, sort)
                );

SearchHits<ElasticSearchEntity> searchHits = elasticsearchRestTemplate.search(query, ElasticSearchEntity.class, IndexCoordinates.of("index-*"));

发现问题

各种查文档,都没有对spring-data-elasticsearch的这个异常处理方案,所以只能自己查了
既然是ElasticSearch的错误就去原生查询,查询时发现,ElasticSearch的dataTimestamp的字段有两个,因为没有加载mapping默认识别string类型,默认还会为string类型创建keyword,所以这时候有两种类型,使用的时候就要注意调用区分,如果keyword声明成功,就只有一个keyword类型,直接使用原字段就可以
在这里插入图片描述

原因

查询ElasticSearch文档对keyword的介绍,大致说一下我的理解,有问题望指正
Keyword是相当于对Text的一个补充,设置Keyword类型或当Text设置分词器、索引的时候,就会创建一个.keyword字段,用于更快速的查询,所以文本字段需要使用索引时,不可以直接使用原字段,要利用.keyword字段操作就可以了

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐