Migrate Spring Data Elasticsearch from 3.x version to 4.x

Spring Data Elasticsearch 从 3.X 迁移到 4.X

因为需要将产品的 spring boot 2.1.6.RELEASE 升级到 2.3.12.RELEASE,升级过程中发现有一些需要迁移的部分,特此整理记录。 本文不是迁移指南,仅仅是工作中遇到的迁移问题笔记

依赖组件

组件迁移前迁移后
spring-data-elasticsearch3.1.94.0.9
elasticsearch6.4.37.6.2

GetQuery 已废弃

以下代码中 GetQuery 已经被废弃,并且 getQuery.setId 方法已经被删除

GetQuery getQuery = new GetQuery();
getQuery.setId(globalTxId);
GlobalTransactionDocument globalTransaction = this.template
    .queryForObject(getQuery, GlobalTransactionDocument.class);

使用以下代码替换

Query query = new NativeSearchQueryBuilder().withIds(Collections.singletonList(globalTxId)).build();
SearchHit<GlobalTransactionDocument> result =  this.template.searchOne(query, GlobalTransactionDocument.class);
GlobalTransactionDocument globalTransaction = result.getContent();

ElasticsearchTemplate 已废弃

使用 ElasticsearchRestTemplate 代替 ElasticsearchTemplate

ElasticsearchRestTemplate 索引操作

ElasticsearchTemplate 的 getClient().admin().indices() 用法已经废弃

IndicesExistsRequest request = new IndicesExistsRequest(INDEX_NAME);
if (this.template.getClient().admin().indices().exists(request).actionGet().isExists()) {

}

迁移后 ElasticsearchRestTemplate 的用法

if (this.template.indexOps(IndexCoordinates.of(INDEX_NAME)).exists()) {

}

ElasticsearchRestTemplate 翻页查询

ElasticsearchTemplate 原来的用法

QueryBuilder query = QueryBuilders.termQuery("state.keyword", state);
SearchResponse response = this.template.getClient().prepareSearch(INDEX_NAME)
    .setTypes(INDEX_TYPE)
    .setQuery(query)
    .addSort(SortBuilders.fieldSort("beginTime").order(SortOrder.DESC).unmappedType("date"))
    .setSize(size)
    .setFrom(page * size)
    .execute()
    .actionGet();

迁移后 ElasticsearchRestTemplate 的用法

NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
queryBuilder.withSearchType(SearchType.valueOf(INDEX_TYPE));
if (state != null && state.trim().length() > 0) {
  queryBuilder.withQuery(QueryBuilders.termQuery("state.keyword", state));
} else {
  queryBuilder.withQuery(QueryBuilders.matchAllQuery());
}
queryBuilder.withSort(SortBuilders.fieldSort("beginTime").order(SortOrder.DESC).unmappedType("date"));
queryBuilder.withPageable(PageRequest.of(page, size));

SearchHits<GlobalTransactionDocument> result = this.template.search(queryBuilder.build(), GlobalTransactionDocument.class);

ElasticsearchTemplate.query 方法以删除

this.template.query 方法以废弃,SearchQuery 类已被移除,NativeSearchQueryBuilder 的 withIndices 方法已被移除

public Map<String, Long> getTransactionStatistics() {
  TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders
      .terms("count_group_by_state").field("state.keyword");
  SearchQuery searchQuery = new NativeSearchQueryBuilder()
      .withIndices(INDEX_NAME)
      .addAggregation(termsAggregationBuilder)
      .build();
  return this.template.query(searchQuery, response -> {
    Map<String, Long> statistics = new HashMap<>();
    if (response.getHits().getTotalHits().value > 0) {
      final StringTerms groupState = response.getAggregations().get("count_group_by_state");
      statistics = groupState.getBuckets()
          .stream()
          .collect(Collectors.toMap(MultiBucketsAggregation.Bucket::getKeyAsString,
              MultiBucketsAggregation.Bucket::getDocCount));
    }
    return statistics;
  });
}

迁移后 ElasticsearchRestTemplate 新方法

public Map<String, Long> getTransactionStatistics() {
  Map<String, Long> statistics = new HashMap<>();

  Query query = new NativeSearchQueryBuilder()
      .addAggregation(AggregationBuilders.terms("count_group_by_state").field("state.keyword"))
      .build();
  SearchHits<Map> result = this.template.search(query,Map.class,IndexCoordinates.of(INDEX_NAME));
  if (result.getTotalHits() > 0) {
    final StringTerms groupState = result.getAggregations().get("count_group_by_state");
    statistics = groupState.getBuckets()
        .stream()
        .collect(Collectors.toMap(MultiBucketsAggregation.Bucket::getKeyAsString,
            MultiBucketsAggregation.Bucket::getDocCount));
  }

  return statistics;
}

索引刷新

ElasticsearchTemplate 的方法

template.refresh(INDEX_NAME);

迁移后 ElasticsearchRestTemplate 的方法

template.indexOps(IndexCoordinates.of(INDEX_NAME)).refresh();

Spring Boot 配置

旧的配置

spring.data.elasticsearch.cluster-nodes=localhost:9300

迁移后的配置

spring.elasticsearch.rest.uris=http://localhost:9200