本文最后更新于 2024-04-09,欢迎来到我的Blog! https://www.zpeng.site/

SpringBoot整合Elasticearch

spring-boot-starter-data-elasticsearch

依赖

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

application.yml

spring:
  elasticsearch:
    rest:
      uris: 127.0.0.1:9200
      connection-timeout: 1s
      read-timeout: 30s

ElasticSearch

package com.example.learning.elasticsearch;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

/**
 * @ClassName ElasticSearch
 * @Description:
 * @Author: zpeng
 * @CreateDate: 2024/4/8 20:41
 */

//@Document 文档对象 (索引信息、文档类型 )
@Document(indexName = "blog")
@Data
public class ElasticSearch {

    //@Id 文档主键 唯一标识
    //@Field 每个文档的字段配置(类型、是否分词、是否存储、分词器 )
    @Id
    @Field(type = FieldType.Integer)
    private Integer id;

    @Field(type = FieldType.Text)
    private String title;

    @Field(type = FieldType.Text)
    private String content;

    @Field(type = FieldType.Double)
    private Double price;
}

ElasticSearchRepository

package com.example.learning.elasticsearch;

import org.springframework.data.elasticsearch.annotations.Highlight;
import org.springframework.data.elasticsearch.annotations.HighlightField;
import org.springframework.data.elasticsearch.annotations.HighlightParameters;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @ClassName ElasticSearchRepository
 * @Description:
 * @Author: zpeng
 * @CreateDate: 2024/4/8 20:47
 */
@Repository
public interface ElasticSearchRepository extends ElasticsearchRepository<ElasticSearch, Integer> {

    /**
     * 查询内容标题查询
     *
     * @param title   标题
     * @param content 内容
     * @return 返回关键字高亮的结果集
     */
    @Highlight(
            fields = {@HighlightField(name = "title"), @HighlightField(name = "content")},
            parameters = @HighlightParameters(preTags = {"<span style='color:red'>"}, postTags = {"</span>"}, numberOfFragments = 0)
    )
    List<SearchHit<ElasticSearch>> findByTitleOrContent(String title, String content);

}

ElasticSearchService

package com.example.learning.elasticsearch;

import org.springframework.data.elasticsearch.core.SearchHit;

import java.util.List;

/**
 * @ClassName ElasticSearchService
 * @Description:
 * @Author: zpeng
 * @CreateDate: 2024/4/8 20:48
 */
public interface ElasticSearchService {

    //保存和修改
    void save(ElasticSearch article);

    //查询id
    ElasticSearch findById(Integer id);

    //删除指定ID数据
    void deleteById(Integer id);

    long count();

    boolean existsById(Integer id);

    List<SearchHit<ElasticSearch>> findByTitleOrContent(String title, String content);

}

ElasticSearchServiceImpl

package com.example.learning.elasticsearch;

import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * @ClassName ElasticSearchServiceImpl
 * @Description:
 * @Author: zpeng
 * @CreateDate: 2024/4/8 20:48
 */
@Service
public class ElasticSearchServiceImpl implements ElasticSearchService {

    @Resource
    private ElasticSearchRepository ElasticSearchRepository;


    @Override
    public void save(ElasticSearch ElasticSearch) {
        ElasticSearchRepository.save(ElasticSearch);
    }

    @Override
    public ElasticSearch findById(Integer id) {
        return ElasticSearchRepository.findById(id).orElse(new ElasticSearch());
    }

    @Override
    public void deleteById(Integer id) {
        ElasticSearchRepository.deleteById(id);
    }

    @Override
    public long count() {
        return ElasticSearchRepository.count();
    }

    @Override
    public boolean existsById(Integer id) {
        return ElasticSearchRepository.existsById(id);
    }

    @Override
    public List<SearchHit<ElasticSearch>> findByTitleOrContent(String title, String content) {
        return ElasticSearchRepository.findByTitleOrContent(title, content);
    }

}

EsTest

package com.example.learning.elasticsearch;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.util.List;

/**
 * @ClassName EsTest
 * @Description:
 * @Author: zpeng
 * @CreateDate: 2024/4/8 20:50
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class EsTest {

    @Resource
    private ElasticSearchService elasticSearchService;

    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
    /**创建索引和映射*/
    @Test
    public void createIndex(){

//        elasticsearchTemplate.createIndex(ElasticSearch.class);
//        elasticsearchTemplate.putMapping(ElasticSearch.class);
    }

    /**添加文档或者修改文档(以id为准)*/
    @Test
    public void saveElasticSearch(){
        ElasticSearch elasticSearch = new ElasticSearch();
        elasticSearch.setId(2);
        elasticSearch.setTitle("整合SpringBoot和Elasticearch");
        elasticSearch.setContent("整合SpringBoot和Elasticearch1111111111111111111111111111111111111111111111111111");
        elasticSearchService.save(elasticSearch);
    }
    @Test
    public void findById(){
        ElasticSearch byId = elasticSearchService.findById(2);
        System.out.println(byId);
    }
    @Test
    public void deleteById(){
        elasticSearchService.deleteById(100);

    }
    @Test
    public void count(){
        long count = elasticSearchService.count();
        System.out.println(count);
    }
    @Test
    public void existsById(){
        boolean b = elasticSearchService.existsById(102);

        System.out.println(b);
    }
    @Test
    public void findByTitleOrContent(){
        List<SearchHit<ElasticSearch>> byTitleOrContent = elasticSearchService.findByTitleOrContent("xxxxxxSpringData","elasticSearch");
        for (SearchHit<ElasticSearch> elasticSearchService : byTitleOrContent) {
            List<String> title = elasticSearchService.getHighlightField("title");
            System.out.println(title);
            List<String> content = elasticSearchService.getHighlightField("content");
            System.out.println(content);

        }
    }
}

测试

GET /blog/_search
{
  "query": {
    "match_all": {}
  }
}

2、elasticsearch-rest-high-level-client

依赖

        <!-- Elasticsearch REST client -->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
        </dependency>

application.yml

spring:
  elasticsearch:
    rest:
      uris: 127.0.0.1:9200
      connection-timeout: 1s
      read-timeout: 30s

EsConfig

package com.example.learning.elasticsearch.esclient;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @ClassName ElasticsearchClientConfig
 * @Description:
 * @Author: zpeng
 * @CreateDate: 2024/4/9 13:06
 */
@Configuration
public class EsConfig {

    @Bean(destroyMethod = "close")
    public RestHighLevelClient restHighLevelClient() {
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("localhost", 9200, "http")
                ));
        return client;
    }
}

IRestHighLevelClientService

package com.example.learning.elasticsearch.esclient;

import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.index.reindex.BulkByScrollResponse;

import org.elasticsearch.action.update.UpdateResponse;

import java.io.IOException;

/**
 * @ClassName IRestHighLevelClientService
 * @Description:
 * @Author: zpeng
 * @CreateDate: 2024/4/9 14:07
 */
public interface IRestHighLevelClientService {

    // 创建索引
    CreateIndexResponse createIndex() throws IOException;

    // 删除索引
    AcknowledgedResponse deleteIndex() throws IOException;

    // 查看索引是否存在
    boolean existIndex() throws IOException;

    // 更新索引的settings配置
    AcknowledgedResponse updateIndexSettings() throws IOException;

    // 更新索引的mapping配置
    AcknowledgedResponse updateIndexMapping() throws IOException;

    // 新增文档
    IndexResponse addDocument() throws IOException;

    // 修改文档
    UpdateResponse updateDocument() throws IOException;

    // 根据id删除文档
    DeleteResponse deleteDocumentById() throws IOException;

    // 根据条件删除文档
    BulkByScrollResponse deleteDocumentByCon() throws IOException;

    // 批量操作文档
    BulkResponse bulkDocument() throws IOException;

    // 查询操作
    SearchResponse searchDocument1() throws IOException;

    // 查询操作2
    SearchResponse searchDocument2() throws IOException;

    // 高亮查询
    SearchResponse searchDocument3() throws IOException;
}

RestHighLevelClientServiceImpl

package com.example.learning.elasticsearch.esclient;

import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.PutMappingRequest;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.AvgAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName RestHighLevelClientServiceImpl
 * @Description:
 * @Author: zpeng
 * @CreateDate: 2024/4/9 14:08
 */
@Service
public class RestHighLevelClientServiceImpl implements IRestHighLevelClientService {

    // 引入RestHighLevelClient
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    // 新建索引
    @Override
    public CreateIndexResponse createIndex() throws IOException {
        String indexName = "student";
        CreateIndexRequest request = new CreateIndexRequest(indexName.toLowerCase());
        request.settings(Settings.builder()
                .put("index.number_of_shards", 5)
                .put("index.number_of_replicas", 0)
        );
        // mapping部分,除了用json字符串来定义外,还可以使用Map或者XContentBuilder
        // 这里使用XContentBuilder
        XContentBuilder builder = XContentFactory.jsonBuilder();
        builder.startObject();
        {
            builder.startObject("properties");
            {
                builder.startObject("id");
                {
                    builder.field("type", "integer");
                }
                builder.endObject();
                builder.startObject("name");
                {
                    builder.field("type", "text");
                }
                builder.endObject();
                builder.startObject("age");
                {
                    builder.field("type", "integer");
                }
                builder.endObject();
                builder.startObject("description");
                {
                    builder.field("type", "text");
                    builder.field("analyzer", "ik_max_word");
                }
                builder.endObject();
                builder.startObject("birthday");
                {
                    builder.field("type", "date");
                }
                builder.endObject();
            }
            builder.endObject();
        }
        builder.endObject();
        request.mapping(builder);
        // 同步的方式执行
        CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
        // 异步的方式执行
        restHighLevelClient.indices().createAsync(request, RequestOptions.DEFAULT, new ActionListener<CreateIndexResponse>() {
            @Override
            public void onResponse(CreateIndexResponse createIndexResponse1) {
                System.out.println("执行情况:" + createIndexResponse1);
            }

            @Override
            public void onFailure(Exception e) {
                System.out.println("执行失败的原因:" + e.getMessage());
            }
        });
        return createIndexResponse;
    }

    // 删除索引
    @Override
    public AcknowledgedResponse deleteIndex() throws IOException {
        String indexName = "student";
        DeleteIndexRequest indexRequest = new DeleteIndexRequest(indexName);
        // 同步执行
        AcknowledgedResponse delete = restHighLevelClient.indices().delete(indexRequest, RequestOptions.DEFAULT);
        // 异步执行
        /*
        restHighLevelClient.indices().deleteAsync(indexRequest, RequestOptions.DEFAULT, new ActionListener<AcknowledgedResponse>() {
            @Override
            public void onResponse(AcknowledgedResponse acknowledgedResponse) {
                System.out.println("执行情况:" + acknowledgedResponse);
            }

            @Override
            public void onFailure(Exception e) {
                System.out.println("执行失败的原因:" + e.getMessage());
            }
        });
        */
        return delete;
    }

    // 查看索引是否存在
    @Override
    public boolean existIndex() throws IOException {
        String indexName = "student";
        GetIndexRequest request = new GetIndexRequest(indexName);
        // 同步执行
        boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
        // 异步执行
        /*
        restHighLevelClient.indices().existsAsync(request, RequestOptions.DEFAULT, new ActionListener<Boolean>() {
            @Override
            public void onResponse(Boolean aBoolean) {
                System.out.println("执行情况:" + aBoolean);
            }

            @Override
            public void onFailure(Exception e) {
                System.out.println("执行失败的原因:" + e.getMessage());
            }
        });
        */
        return exists;
    }

    // 更新索引的settings配置
    @Override
    public AcknowledgedResponse updateIndexSettings() throws IOException {
        String indexName = "student";
        UpdateSettingsRequest request = new UpdateSettingsRequest(indexName);
        String settingKey = "index.number_of_replicas";
        int settingValue = 2;
        Settings.Builder settingsBuilder = Settings.builder().put(settingKey, settingValue);
        request.settings(settingsBuilder);
        // 是否更新已经存在的settings配置默认false
        request.setPreserveExisting(true);
        // 更新settings配置(同步)
        AcknowledgedResponse updateSettingsResponse = restHighLevelClient.indices().putSettings(request, RequestOptions.DEFAULT);
        // 更新settings配置(异步)
        /*
        restHighLevelClient.indices().putSettingsAsync(request, RequestOptions.DEFAULT, new ActionListener<AcknowledgedResponse>() {
            @Override
            public void onResponse(AcknowledgedResponse acknowledgedResponse) {
                System.out.println("执行情况:" + acknowledgedResponse);
            }

            @Override
            public void onFailure(Exception e) {
                System.out.println("执行失败的原因:" + e.getMessage());
            }
        });
        */
        return updateSettingsResponse;
    }

    // 更新索引的mapping配置
    @Override
    public AcknowledgedResponse updateIndexMapping() throws IOException {
        String indexName = "student";
        PutMappingRequest request = new PutMappingRequest(indexName);
        XContentBuilder builder = XContentFactory.jsonBuilder();
        builder.startObject();
        {
            builder.startObject("properties");
            {
                // 会在以前索引的基础上新增sex字段
                builder.startObject("sex");
                {
                    builder.field("type", "integer");
                }
                builder.endObject();
            }
            builder.endObject();
        }
        builder.endObject();
        request.source(builder);
        // 新增mapping配置(同步)
        AcknowledgedResponse putMappingResponse = restHighLevelClient.indices().putMapping(request, RequestOptions.DEFAULT);
        // 新增mapping配置(异步)
        /*
        restHighLevelClient.indices().putMappingAsync(request, RequestOptions.DEFAULT, new ActionListener<AcknowledgedResponse>() {
            @Override
            public void onResponse(AcknowledgedResponse acknowledgedResponse) {
                System.out.println("执行情况:" + acknowledgedResponse);
            }

            @Override
            public void onFailure(Exception e) {
                System.out.println("执行失败的原因:" + e.getMessage());
            }
        });
        */
        return putMappingResponse;
    }

    // 新增文档
    @Override
    public IndexResponse addDocument() throws IOException {
        String indexName = "student";
        IndexRequest request = new IndexRequest(indexName);
        // id为1的数据
        request.id("4");
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("id", 4);
        jsonMap.put("name", "yulo");
        jsonMap.put("age", 16);
        jsonMap.put("description", "十分陌生地方粉色粉色发");
        jsonMap.put("birthday", new Date());
        jsonMap.put("sex", 1);
        request.source(jsonMap);
        request.routing("routing");
        // 同步方式
        IndexResponse indexResponse = restHighLevelClient.index(request, RequestOptions.DEFAULT);
        // 异步方式
        /*
        restHighLevelClient.indexAsync(request, RequestOptions.DEFAULT, new ActionListener<IndexResponse>() {
            @Override
            public void onResponse(IndexResponse indexResponse) {
                System.out.println("执行情况: " + indexResponse);
            }

            @Override
            public void onFailure(Exception e) {
                System.out.println("执行失败的原因:" + e.getMessage());
            }
        });
        */
        return indexResponse;
    }

    // 修改文档
    @Override
    public UpdateResponse updateDocument() throws IOException {
        String indexName = "student";
        // 传入索引名称和需要更新的Document的id
        UpdateRequest request = new UpdateRequest(indexName, "1");
        // 更新的内容会与数据本身合并,若存在则更新,不存在则新增
        // 组装更新内容的数据结构有四种: json字符串、Map、XContentBuilder、Key-Value
        // json字符串
        /*
        String jsonString = "{" +
                "\"updated\":\"2020-03-29\"," +
                "\"reason\":\"daily update\"" +
                "}";
        request.doc(jsonString);
        */
        // Map
        /*
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("updated", new Date());
        jsonMap.put("reason", "daily update");
        request.doc(jsonMap);
        */
        // XContentBuilder
        /*
        XContentBuilder builder = XContentFactory.jsonBuilder();
        builder.startObject();
        builder.timeField("updated", new Date());
        builder.timeField("reason", "daily update");
        builder.endObject();
        request.doc(builder);
        */
        // Key-Value,可以包含多个键值对
        request.doc("description", "tom是一个好学生,考上大学肯定没有问题!");
        // 同步的方式发送更新请求
        UpdateResponse updateResponse = restHighLevelClient.update(request, RequestOptions.DEFAULT);
        // 异步方式
        /*
        restHighLevelClient.updateAsync(request, RequestOptions.DEFAULT, new ActionListener<UpdateResponse>() {
            @Override
            public void onResponse(UpdateResponse updateResponse) {
                System.out.println("执行情况: " + updateResponse);

            }

            @Override
            public void onFailure(Exception e) {
                System.out.println("执行失败的原因:" + e.getMessage());
            }
        });
        */
        return updateResponse;

    }

    // 根据id删除文档
    @Override
    public DeleteResponse deleteDocumentById() throws IOException {
        String indexName = "student";
        DeleteRequest deleteRequest = new DeleteRequest(indexName, "1");
        // 同步方式
        DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
        // 异步方式
        /*
        restHighLevelClient.deleteAsync(deleteRequest, RequestOptions.DEFAULT, new ActionListener<DeleteResponse>() {
            @Override
            public void onResponse(DeleteResponse deleteResponse) {
                System.out.println("执行情况: " + deleteResponse);

            }

            @Override
            public void onFailure(Exception e) {
                System.out.println("执行失败的原因:" + e.getMessage());
            }
        });
        */
        return deleteResponse;
    }

    // 根据条件删除文档
    @Override
    public BulkByScrollResponse deleteDocumentByCon() throws IOException {
        String indexName = "student";
        DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest(indexName);
        // 待删除的数据需要满足的条件
        deleteByQueryRequest.setQuery(new TermQueryBuilder("name", "tom"));
        // 忽略版本冲突
        deleteByQueryRequest.setConflicts("proceed");
        // 同步的方式删除
        BulkByScrollResponse deleteResponse = restHighLevelClient.deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT);
        // 异步的方式
        /*
        restHighLevelClient.deleteByQueryAsync(deleteByQueryRequest, RequestOptions.DEFAULT, new ActionListener<BulkByScrollResponse>() {
            @Override
            public void onResponse(BulkByScrollResponse bulkByScrollResponse) {
                System.out.println("执行情况: " + deleteResponse);

            }

            @Override
            public void onFailure(Exception e) {
                System.out.println("执行失败的原因:" + e.getMessage());
            }
        });
        */
        return deleteResponse;
    }

    // 批量操作文档
    @Override
    public BulkResponse bulkDocument() throws IOException {
        String indexName = "student";
        BulkRequest request = new BulkRequest();
        // 普通的PUT操作,相当于全量替换或新增
        request.add(new IndexRequest(indexName).id("2").source(XContentType.JSON, "name", "zsx", "age", "25"));
        // 更新操作
        request.add(new UpdateRequest(indexName, "2").doc(XContentType.JSON, "sex", 1));
        // 删除操作
        request.add(new DeleteRequest(indexName, "2"));
        // 同步操作
        BulkResponse bulkResponse = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
        boolean hasFailures = bulkResponse.hasFailures();
        System.out.println("批量操作是否失败:" + hasFailures);
        BulkItemResponse[] items = bulkResponse.getItems();
        for (BulkItemResponse item : items) {
            System.out.println(item.status());
        }
        // 异步操作
        /*
        restHighLevelClient.bulkAsync(request, RequestOptions.DEFAULT, new ActionListener<BulkResponse>() {
            @Override
            public void onResponse(BulkResponse bulkItemResponses) {
                System.out.println("执行情况: " + bulkItemResponses);

            }

            @Override
            public void onFailure(Exception e) {
                System.out.println("执行失败的原因:" + e.getMessage());
            }
        });
        */
        return bulkResponse;
    }

    // 查询操作1
    @Override
    public SearchResponse searchDocument1() throws IOException {
        String indexName = "student";
        SearchRequest searchRequest = new SearchRequest(indexName);
        BoolQueryBuilder booleanQueryBuilder = QueryBuilders.boolQuery();
        // 过滤出年龄在15~40岁之间的document
        booleanQueryBuilder.filter(QueryBuilders.rangeQuery("age").from(15).to(40));
        // bool must条件, 找出description字段中包含学生的document
        booleanQueryBuilder.must(QueryBuilders.matchQuery("description", "学生"));
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 执行查询条件
        // sourceBuilder.query(QueryBuilders.matchAllQuery());
        sourceBuilder.query(booleanQueryBuilder);
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", "tom");
        sourceBuilder.query(matchQueryBuilder);
        //聚合年龄分布
        TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age");
        sourceBuilder.aggregation(ageAgg);
        //聚合平均年龄
        AvgAggregationBuilder balanceAvg = AggregationBuilders.avg("ageAvg").field("age");
        sourceBuilder.aggregation(balanceAvg);
        // 分页查询
        sourceBuilder.from(0);
        sourceBuilder.size(5);
        // 排序
        sourceBuilder.sort("age", SortOrder.DESC);
        //sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(sourceBuilder);
        // 同步的方式发送请求
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            String hitString = hit.getSourceAsString();
            System.out.println(hitString);
        }
        // 异步方式发送请求
        /*
        restHighLevelClient.searchAsync(searchRequest, RequestOptions.DEFAULT, new ActionListener<SearchResponse>() {

            @Override
            public void onResponse(SearchResponse searchResponse) {
                System.out.println("执行情况: " + searchResponse);

            }

            @Override
            public void onFailure(Exception e) {
                System.out.println("执行失败的原因:" + e.getMessage());
            }
        });
        */
        return searchResponse;
    }

    // 查询操作2
    @Override
    public SearchResponse searchDocument2() throws IOException {
        String indexName = "student";
        SearchRequest searchRequest = new SearchRequest(indexName);
        //构建搜索条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
                // 在student索引的description和name字段中都查询“tom”
                .query(QueryBuilders.multiMatchQuery("粉色", "description", "name"))
                // matchQuery是模糊查询,会对key进行分词
                // searchSourceBuilder.query(QueryBuilders.matchQuery(key,value));
                // termQuery是精准查询
                // searchSourceBuilder.query(QueryBuilders.termQuery(key,value));
                .sort(SortBuilders.fieldSort("age").order(SortOrder.DESC))
                // 一个可选项,用于控制允许搜索的时间
                // searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
                // 指定从哪条开始查询
                .from(0)
                // 需要查出的总记录条数
                .size(10);
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            String hitString = hit.getSourceAsString();
            System.out.println(hitString);
        }
        // 异步方式发送请求
        /*
        restHighLevelClient.searchAsync(searchRequest, RequestOptions.DEFAULT, new ActionListener<SearchResponse>() {

            @Override
            public void onResponse(SearchResponse searchResponse) {
                System.out.println("执行情况: " + searchResponse);

            }

            @Override
            public void onFailure(Exception e) {
                System.out.println("执行失败的原因:" + e.getMessage());
            }
        });
        */
        return searchResponse;
    }

    // 高亮查询
    @Override
    public SearchResponse searchDocument3() throws IOException {
        String indexName = "student";
        SearchRequest searchRequest = new SearchRequest(indexName);
        // 高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("name");
        highlightBuilder.field("description");
        highlightBuilder.requireFieldMatch(false);
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        // 构建搜索条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
                .query(QueryBuilders.multiMatchQuery("tom", "description", "name"))
                .sort(SortBuilders.fieldSort("age").order(SortOrder.DESC))
                // 指定从哪条开始查询
                .from(0)
                // 需要查出的总记录条数
                .size(10)
                //高亮
                .highlighter(highlightBuilder);
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            String hitString = hit.getSourceAsString();
            System.out.println(hitString);
            // 处理高亮显示的结果
            HighlightField titleField = hit.getHighlightFields().get("name");
            if (titleField != null) {
                // 新建一个对象,把该属性的值重新覆盖
                System.out.println(titleField.getFragments()[0].toString());
            }
            HighlightField contentField = hit.getHighlightFields().get("description");
            if (contentField != null) {
                System.out.println(contentField.getFragments()[0].toString());
            }
        }
        // 异步方式发送请求
        /*
        restHighLevelClient.searchAsync(searchRequest, RequestOptions.DEFAULT, new ActionListener<SearchResponse>() {

            @Override
            public void onResponse(SearchResponse searchResponse) {
                System.out.println("执行情况: " + searchResponse);

            }

            @Override
            public void onFailure(Exception e) {
                System.out.println("执行失败的原因:" + e.getMessage());
            }
        });
        */
        return searchResponse;
    }
}

EsclientTest

package com.example.learning.elasticsearch;


import com.example.learning.elasticsearch.esclient.IRestHighLevelClientService;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.elasticsearch.action.update.UpdateResponse;

import java.io.IOException;

/**
 * @ClassName EsclientTest
 * @Description:
 * @Author: zpeng
 * @CreateDate: 2024/4/9 14:18
 */

@SpringBootTest
class EsclientTest {

    @Autowired
    private IRestHighLevelClientService iRestHighLevelClientService;

    // 新建索引
    @Test
    void createIndex() throws IOException {
        CreateIndexResponse createIndexResponse = iRestHighLevelClientService.createIndex();
        System.out.println("新建的索引是:" + createIndexResponse.index());
    }

    // 删除索引
    @Test
    void deleteIndex() throws IOException {
        AcknowledgedResponse acknowledgedResponse = iRestHighLevelClientService.deleteIndex();
        System.out.println("删除索引是否成功:" + acknowledgedResponse.isAcknowledged());
    }

    // 查看索引是否存在
    @Test
    void existIndex() throws IOException {
        Boolean aBoolean = iRestHighLevelClientService.existIndex();
        System.out.println("索引是否存在:" + aBoolean);
    }

    // 更新索引的settings配置
    @Test
    void updateIndexSettings() throws IOException {
        AcknowledgedResponse acknowledgedResponse = iRestHighLevelClientService.updateIndexSettings();
        System.out.println("是否更新settings配置成功:" + acknowledgedResponse.isAcknowledged());
    }

    // 更新索引的mapping配置
    @Test
    void updateIndexMapping() throws IOException {
        AcknowledgedResponse acknowledgedResponse = iRestHighLevelClientService.updateIndexMapping();
        System.out.println("是否更新mapping配置成功:" + acknowledgedResponse.isAcknowledged());
    }

    // 新增文档
    @Test
    void addDocument() throws IOException {
        IndexResponse indexResponse = iRestHighLevelClientService.addDocument();
        System.out.println("新增文档是否成功:" + indexResponse.status());
    }

    // 修改文档
    @Test
    void addDocumentByCon() throws IOException {
        UpdateResponse updateResponse = iRestHighLevelClientService.updateDocument();
        // System.out.println("修改文档是否成功:" + updateResponse.status());
    }

    // 根据id删除文档
    @Test
    void deleteDocumentById() throws IOException {
        DeleteResponse deleteResponse = iRestHighLevelClientService.deleteDocumentById();
        System.out.println("删除文档是否成功:" + deleteResponse.status());
    }

    // 根据条件删除文档
    @Test
    void deleteDocumentByCon() throws IOException {
        BulkByScrollResponse bulkByScrollResponse = iRestHighLevelClientService.deleteDocumentByCon();
        System.out.println("删除文档是否成功:" + bulkByScrollResponse.getDeleted());
    }

    // 批量操作文档
    @Test
    void bulkDocument() throws IOException {
        BulkResponse bulkItemResponses = iRestHighLevelClientService.bulkDocument();
        System.out.println("批量操作文档是否成功:" + bulkItemResponses.status());
    }

    // 查询操作1
    @Test
    void searchDocument1() throws IOException {
        SearchResponse searchResponse = iRestHighLevelClientService.searchDocument1();
        System.out.println("查询数据的总数:" + searchResponse.getHits().getHits().length);
        System.out.println("符合条件的文档最大得分: " + searchResponse.getHits().getMaxScore());
    }

    // 查询操作2
    @Test
    void searchDocument2() throws IOException {
        SearchResponse searchResponse = iRestHighLevelClientService.searchDocument2();
        System.out.println("查询数据的总数:" + searchResponse.getHits().getHits().length);
        System.out.println("符合条件的文档最大得分: " + searchResponse.getHits().getMaxScore());
    }

    // 高亮查询
    @Test
    void searchDocument3() throws IOException {
        SearchResponse searchResponse = iRestHighLevelClientService.searchDocument3();
        System.out.println("查询数据的总数:" + searchResponse.getHits().getHits().length);
        System.out.println("符合条件的文档最大得分: " + searchResponse.getHits().getMaxScore());
    }
}