[JAVA]elasticsearchrepository中的所有方法都已弃用

版本选择

要升级到Elasticsearch8.2,首先要选择合适的版本。

在pom.xml里修改SpringBoot依赖的版本为2.6.6

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.6.6</version>
  <relativePath/> <!-- lookup parent from repository -->
</parent>

Spring Data Elasticsearch的依赖:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

遇到的问题

在application.yml中,原来我们用来配置Elasticsearch访问路径和集群名称的配置已经不建议使用了,应该如下所配置:

server:
  port: 8090
 
 
spring:
  redis:
    database: 0
    port: 6379
    host: 192.168.69.201
    password: wtl1992
 
  elasticsearch:
    password: 'XXXXXXXXXXXX'
    username: elastic
    # uris:是个以,分隔的数组
    uris: http://ljxwtl.cn:9200

最大的问题还是ElasticsearchTemplate已经过时了,不建议使用了!!!

使用ElasticsearchRestTemplate的search()方法来代替

总之:
Elasticsearch从6.x升级到7.x改动还真不是一般的大,ElasticsearchTemplate不建议使用了,改为使用ElasticsearchRestTemplate,ElasticsearchRepository实现复杂查询的方法也不建议使用了。从此我们简单的数据操作可以使用ElasticsearchRepository,而复杂的数据操作只能使用ElasticsearchRestTemplate了。

API的使用:

Person.java:

package ljxwtl;
 
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
 
import java.io.Serializable;
import java.util.Date;
 
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "person",createIndex = true)
public class Person implements Serializable {
    @Id
    @Field(type = FieldType.Auto)
    private String id;
    @Field(type = FieldType.Text,index = true)
    private String name;
    @Field(type = FieldType.Integer,index = true)
    private Integer age;
    @Field(type = FieldType.Keyword,index = true)
    private String sex;
    @Field(type = FieldType.Keyword,index = true)
    private String tel;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Field(type = FieldType.Date, format = DateFormat.date_time, pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
}

PersonRepository.java:

package ljxwtl.dao;
 
import ljxwtl.Person;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
 
/**
 * @author: wtl
 * @License: (C) Copyright 2022, wtl Corporation Limited.
 * @Contact: 1050100468@qq.com
 * @Date: 2022/4/10 8:20
 * @Version: 1.0
 * @Description:
 */
public interface PersonRepository extends ElasticsearchRepository<Person,String> {
}

测试类:

package ljxwtl;
 
import ljxwtl.dao.PersonRepository;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.*;
import org.springframework.data.elasticsearch.core.clients.elasticsearch7.ElasticsearchAggregations;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
import org.springframework.data.elasticsearch.core.query.UpdateResponse;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
 
/**
 * @author: wtl
 * @License: (C) Copyright 2022, wtl Corporation Limited.
 * @Contact: 1050100468@qq.com
 * @Date: 2022/4/10 7:43
 * @Version: 1.0
 * @Description:
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = SpringBootApplicationMain.class)
public class ApplicationMainTest {
 
    @Resource
    private PersonRepository personRepository;
 
    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
 
    @Test
    public void test(){
        System.out.println(personRepository);
        System.out.println(elasticsearchRestTemplate);
    }
 
    @Test
    public void createIndex(){
        IndexCoordinates indexCoordinates = IndexCoordinates.of("person");
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(indexCoordinates);
        boolean created = indexOperations.create();
        System.out.println(created);
    }
 
    @Test
    public void setIndexMappings(){
        IndexCoordinates indexCoordinates = IndexCoordinates.of("person");
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(indexCoordinates);
        boolean created = indexOperations.putMapping(Person.class);
        System.out.println(created);
    }
 
    @Test
    public void createIndexWithSetSettings(){
        IndexCoordinates indexCoordinates = IndexCoordinates.of("person");
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(indexCoordinates);
        Map<String,Object> settings = new HashMap<>();
 
        //----------------------------------------静态设置开始----------------------------------------------
        // 静态设置:只能在索引创建时或者在状态为 closed index(闭合的索引)上设置
 
        //主分片数,默认为5.只能在创建索引时设置,不能修改
        settings.put("index.number_of_shards",2);
 
        //是否应在索引打开前检查分片是否损坏,当检查到分片损坏将禁止分片被打开
        settings.put("index.shard.check_on_startup","false");//默认值
//        settings.put("index.shard.check_on_startup","checksum");//检查物理损坏
//        settings.put("index.shard.check_on_startup","true");//检查物理和逻辑损坏,这将消耗大量内存和CPU
//        settings.put("index.shard.check_on_startup","fix");//检查物理和逻辑损坏。有损坏的分片将被集群自动删除,这可能导致数据丢失
 
        //自定义路由值可以转发的目的分片数。默认为 1,只能在索引创建时设置。此值必须小于index.number_of_shards
        settings.put("index.routing_partition_size",1);
 
        //默认使用LZ4压缩方式存储数据,也可以设置为 best_compression,它使用 DEFLATE 方式以牺牲字段存储性能为代价来获得更高的压缩比例。
        settings.put("index.codec","best_compression");
        //----------------------------------------静态设置结束----------------------------------------------
 
 
        //----------------------------------------动态设置开始----------------------------------------------
        //每个主分片的副本数。默认为 1。
        settings.put("index.number_of_replicas",0);
 
        //基于可用节点的数量自动分配副本数量,默认为 false(即禁用此功能)
        settings.put("index.auto_expand_replicas",false);
 
        //执行刷新操作的频率,这使得索引的最近更改可以被搜索。默认为 1s。可以设置为 -1 以禁用刷新。
        settings.put("index.refresh_interval","1s");
 
        //用于索引搜索的 from+size 的最大值。默认为 10000
        settings.put("index.max_result_window",10000);
 
        // 在搜索此索引中 rescore 的 window_size 的最大值
        settings.put("index.max_rescore_window",10000);
 
        //设置为 true 使索引和索引元数据为只读,false 为允许写入和元数据更改。
        settings.put("index.blocks.read_only",false);
 
        // 设置为 true 可禁用对索引的读取操作
        settings.put("index.blocks.read",false);
 
        //设置为 true 可禁用对索引的写入操作。
        settings.put("index.blocks.write",false);
 
        // 设置为 true 可禁用索引元数据的读取和写入。
        settings.put("index.blocks.metadata",false);
 
        //索引的每个分片上可用的最大刷新侦听器数
        settings.put("index.max_refresh_listeners",1000);
        //----------------------------------------动态设置结束----------------------------------------------
 
        boolean created = indexOperations.create(settings);
        System.out.println(created);
    }
 
    @Test
    public void deleteIndex(){
        IndexCoordinates indexCoordinates = IndexCoordinates.of("person");
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(indexCoordinates);
        boolean isDeleted = indexOperations.delete();
        System.out.println(isDeleted);
    }
 
    @Test
    public void saveOne(){
        Person person = new Person();
        person.setId("1");
        person.setName("王天龙");
        person.setAge(30);
        person.setSex("man");
        person.setTel("1111111");
        person.setCreateTime(new Date());
 
        Person savePerson = personRepository.save(person);
 
        System.out.println(savePerson);
    }
 
    @Test
    public void updateOne(){
        Document document = Document.create();
        document.setId("1");
        document.put("name","天龙战神");
 
        UpdateQuery.Builder builder = UpdateQuery.builder("1").withDocument(document).withScriptedUpsert(true);
 
        UpdateResponse updateResponse = elasticsearchRestTemplate.update(builder.build(), IndexCoordinates.of("person"));
 
        System.out.println(updateResponse.getResult());
    }
 
    @Test
    public void saveAll(){
        List<Person> personList = new ArrayList<>(3);
        Person person2 = new Person();
        person2.setId("2");
        person2.setName("王天祥");
        person2.setAge(26);
        person2.setSex("男");
        person2.setTel("222222222222");
        person2.setCreateTime(new Date());
        personList.add(person2);
 
        Person person3 = new Person();
        person3.setId("3");
        person3.setName("王杰");
        person3.setAge(31);
        person3.setSex("女");
        person3.setTel("3333333333");
        person3.setCreateTime(new Date());
        personList.add(person3);
        personRepository.saveAll(personList);
    }
 
    @Test
    public void searchMatchAll() throws IOException {
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder().must(new MatchAllQueryBuilder());
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder);
 
        NativeSearchQuery nativeSearchQuery = nativeSearchQueryBuilder.build();
        SearchHits<Person> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Person.class);
 
        searchHits.getSearchHits().forEach(personSearchHit -> {
            Person content = personSearchHit.getContent();
            System.out.println(content);
        });
    }
 
 
    @Test
    public void searchBoolMustWhere(){
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.matchQuery("name","王天龙"));
        boolQueryBuilder.must(QueryBuilders.matchQuery("age",30));
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder);
        NativeSearchQuery nativeSearchQuery = nativeSearchQueryBuilder.build();
        SearchHits<Person> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Person.class);
 
        searchHits.forEach(personSearchHit -> {
            System.out.println(personSearchHit.getContent());
        });
    }
 
    @Test
    public void searchShouldWhere(){
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.should(QueryBuilders.matchQuery("name","天龙"));
        boolQueryBuilder.should(QueryBuilders.matchQuery("age",26));
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder);
        NativeSearchQuery nativeSearchQuery = nativeSearchQueryBuilder.build();
        SearchHits<Person> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Person.class);
        searchHits.forEach(personSearchHit -> {
            System.out.println(personSearchHit.getContent());
        });
    }
 
    @Test
    public void searchRange(){
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age").gte(26).lt(31);
        boolQueryBuilder.filter(rangeQueryBuilder);
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder);
        NativeSearchQuery nativeSearchQuery = nativeSearchQueryBuilder.build();
        SearchHits<Person> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Person.class);
        searchHits.forEach(personSearchHit -> {
            System.out.println(personSearchHit.getContent());
        });
    }
 
 
    /**
     * 聚合搜索
     * 聚合搜索,aggs,类似于group by,对age字段进行聚合,
     */
    @Test
    public void aggregations() {
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withAggregations(AggregationBuilders.terms("count").field("sex"))
                .build();
 
        SearchHits<Person> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Person.class);
        //取出聚合结果
        ElasticsearchAggregations elasticsearchAggregations = (ElasticsearchAggregations) searchHits.getAggregations();
        Aggregations aggregations = elasticsearchAggregations.aggregations();
        Terms terms = (Terms) aggregations.asMap().get("count");
 
        for (Terms.Bucket bucket : terms.getBuckets()) {
            String keyAsString = bucket.getKeyAsString();   // 聚合字段列的值
            long docCount = bucket.getDocCount();           // 聚合字段对应的数量
            System.out.println(keyAsString + " " + docCount);
        }
    }
 
    /**
     * 分页实现
     */
    @Test
    public void searchWithPageable(){
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder().must(new MatchAllQueryBuilder());
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                //分页实现
                .withPageable(PageRequest.of(0,2));
 
        NativeSearchQuery nativeSearchQuery = nativeSearchQueryBuilder.build();
        SearchHits<Person> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Person.class);
 
        searchHits.getSearchHits().forEach(personSearchHit -> {
            Person content = personSearchHit.getContent();
            System.out.println(content);
        });
    }
 
    /**
     * 排序实现
     */
    @Test
    public void searchWithSort(){
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder().must(new MatchAllQueryBuilder());
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                //分页实现
                .withPageable(PageRequest.of(0,10))
                //排序
                .withSorts(SortBuilders.fieldSort("createTime").order(SortOrder.DESC),SortBuilders.fieldSort("age").order(SortOrder.DESC));
 
        NativeSearchQuery nativeSearchQuery = nativeSearchQueryBuilder.build();
        SearchHits<Person> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Person.class);
 
        searchHits.getSearchHits().forEach(personSearchHit -> {
            Person content = personSearchHit.getContent();
            System.out.println(content);
        });
    }
 
    //高并发场景下模拟ES分布式悲观锁的实现
    @Test
    public void highConcurrencyWithPessimisticLock() throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(1);
 
        AtomicInteger failedCount = new AtomicInteger(0);
 
        /**
         * 在testindex未创建的前提下,并发情况下,只能有一个成功,19个失败
         */
        for (int i = 0; i < 20; i++) {
            new Thread(new Task(countDownLatch,failedCount,elasticsearchRestTemplate)).start();
        }
 
        countDownLatch.countDown();
 
        TimeUnit.SECONDS.sleep(10);
 
        System.out.println(failedCount.get());
    }
 
    private class Task implements Runnable {
 
        private CountDownLatch countDownLatch;
        private AtomicInteger failedCount;
        private ElasticsearchRestTemplate elasticsearchRestTemplate;
 
        public Task(CountDownLatch countDownLatch,AtomicInteger failedCount,ElasticsearchRestTemplate elasticsearchRestTemplate){
            this.countDownLatch = countDownLatch;
            this.failedCount = failedCount;
            this.elasticsearchRestTemplate = elasticsearchRestTemplate;
        }
 
        @Override
        public void run() {
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                IndexCoordinates indexCoordinates = IndexCoordinates.of("testindex");
                IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(indexCoordinates);
                boolean created = indexOperations.create();
                System.out.println(created);
            } catch (Exception e) {
                failedCount.getAndIncrement();
            }
        }
    }
 
}

https://blog.csdn.net/wtl1992/article/details/124072854

posted @ 2023-01-10 11:12  未月廿三  阅读(1575)  评论(0编辑  收藏  举报