SpringBoot2.5.6整合Elasticsearch7.12.1

SpringBoot2.5.6整合Elasticsearch7.12.1

下面将通过SpringBoot整合Elasticseach,SpringBoot的版本是2.5.6,Elasticsearch的版本是7.12.1

SpringBoot整合Elasticsearch主要有三种方式,一种是通过elasticsearch-rest-high-level-client,另一

种是通过spring-boot-starter-data-elasticsearch,最后一种是通过transport

RestHighLevelClient 更强大,更灵活,但是不能友好的操作对象,ElasticSearchRepository 对象操作友

好。

官方文档:

https://docs.spring.io/spring-data/elasticsearch/docs/4.0.1.RELEASE/reference/html/#preface

https://spring.io/projects/spring-data-elasticsearch/#learn

https://www.elastic.co/guide/en/elasticsearch/client/java-api/6.2/java-docs.html

1、elasticsearch-rest-high-level-client方式

使用RestHighLevelClient操作

官网地址:

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html

1.1 引入Pom文件的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.6</version>
        <relativePath/>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>spring-boot-elasticsearch1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-elasticsearch1</name>
    <description>spring-boot-elasticsearch1</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.12.1</version>
        </dependency>

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

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

1.2 添加配置文件EsConfig

package com.example.springbootelasticsearch1.config;

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

/**
 * @author zhangshixing
 * @date 2021年11月09日 21:57
 */
@Configuration
public class EsConfig {

    @Value("${elasticsearch.hostname}")
    private String hostname;

    @Value("${elasticsearch.port}")
    private int port;

    /**
     * HighLevelRestConfig
     */
    @Bean
    public RestHighLevelClient restHighLevelClient() {
        // 如果有多个从节点可以持续在内部new多个HttpHost,参数1是IP,参数2是端口,参数3是通信协议
        return new RestHighLevelClient(RestClient.builder(new HttpHost(hostname, port, "http")));
    }
}

1.3 配置yml文件

# es配置
elasticsearch.hostname=127.0.0.1
elasticsearch.port=9200

# 默认配置,在本地启动的时候可以不配置
# spring.elasticsearch.rest.uris=http://127.0.0.1:9200

1.4 service

package com.example.springbootelasticsearch1.service;

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.action.update.UpdateResponse;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.index.reindex.BulkByScrollResponse;

import java.io.IOException;

/**
 * @author zhangshixing
 * @date 2021年11月09日 22:05
 */
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;
}

1.5 serviceImpl

package com.example.springbootelasticsearch1.service.impl;

import com.example.springbootelasticsearch1.service.IRestHighLevelClientService;
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.unit.TimeValue;
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;
import java.util.concurrent.TimeUnit;

/**
 * @author zhangshixing
 * @date 2021年11月09日 22:06
 */
@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("1");
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("id", 1);
        jsonMap.put("name", "tom");
        jsonMap.put("age", 24);
        jsonMap.put("description", "tom是一个好学生");
        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("tom", "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;
    }
}

1.6 测试类

package com.example.springbootelasticsearch1;

import com.example.springbootelasticsearch1.service.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.action.update.UpdateResponse;
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 java.io.IOException;

@SpringBootTest
class SpringBootElasticsearch1ApplicationTests {

    @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());
    }
}

1.7 启动类

package com.example.springbootelasticsearch1;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootElasticsearch1Application {

	public static void main(String[] args) {

		SpringApplication.run(SpringBootElasticsearch1Application.class, args);
	}

}

1.8 测试

1.8.1创建索引

package com.example.springbootelasticsearch1;

import com.example.springbootelasticsearch1.service.IRestHighLevelClientService;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
class SpringBootElasticsearch1ApplicationTests {

    @Autowired
    private IRestHighLevelClientService iRestHighLevelClientService;

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

在这里插入图片描述

在这里插入图片描述

1.8.2 删除索引

package com.example.springbootelasticsearch1;

import com.example.springbootelasticsearch1.service.IRestHighLevelClientService;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
class SpringBootElasticsearch1ApplicationTests {

    @Autowired
    private IRestHighLevelClientService iRestHighLevelClientService;

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

在这里插入图片描述

1.8.3 查看索引是否存在

package com.example.springbootelasticsearch1;

import com.example.springbootelasticsearch1.service.IRestHighLevelClientService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
class SpringBootElasticsearch1ApplicationTests {

    @Autowired
    private IRestHighLevelClientService iRestHighLevelClientService;

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

在这里插入图片描述

我们再次新建索引:

在这里插入图片描述

1.8.4 更新索引的settings配置

package com.example.springbootelasticsearch1;

import com.example.springbootelasticsearch1.service.IRestHighLevelClientService;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
class SpringBootElasticsearch1ApplicationTests {

    @Autowired
    private IRestHighLevelClientService iRestHighLevelClientService;

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

在这里插入图片描述

1.8.5 更新索引的mapping配置

package com.example.springbootelasticsearch1;

import com.example.springbootelasticsearch1.service.IRestHighLevelClientService;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
class SpringBootElasticsearch1ApplicationTests {

    @Autowired
    private IRestHighLevelClientService iRestHighLevelClientService;

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

在这里插入图片描述

在这里插入图片描述

1.8.6 新增文档

package com.example.springbootelasticsearch1;

import com.example.springbootelasticsearch1.service.IRestHighLevelClientService;
import org.elasticsearch.action.index.IndexResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
class SpringBootElasticsearch1ApplicationTests {

    @Autowired
    private IRestHighLevelClientService iRestHighLevelClientService;

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

在这里插入图片描述

在这里插入图片描述

1.8.7 修改文档

package com.example.springbootelasticsearch1;

import com.example.springbootelasticsearch1.service.IRestHighLevelClientService;
import org.elasticsearch.action.update.UpdateResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
class SpringBootElasticsearch1ApplicationTests {

    @Autowired
    private IRestHighLevelClientService iRestHighLevelClientService;

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

在这里插入图片描述

在这里插入图片描述

1.8.8 根据id删除文档

package com.example.springbootelasticsearch1;

import com.example.springbootelasticsearch1.service.IRestHighLevelClientService;
import org.elasticsearch.action.delete.DeleteResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
class SpringBootElasticsearch1ApplicationTests {

    @Autowired
    private IRestHighLevelClientService iRestHighLevelClientService;

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

在这里插入图片描述

在这里插入图片描述

1.8.9 根据条件删除文档

package com.example.springbootelasticsearch1;

import com.example.springbootelasticsearch1.service.IRestHighLevelClientService;
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 java.io.IOException;

@SpringBootTest
class SpringBootElasticsearch1ApplicationTests {

    @Autowired
    private IRestHighLevelClientService iRestHighLevelClientService;

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

新增一条文档,然后再进行测试:

在这里插入图片描述

1.8.10 批量操作文档

package com.example.springbootelasticsearch1;

import com.example.springbootelasticsearch1.service.IRestHighLevelClientService;
import org.elasticsearch.action.bulk.BulkResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
class SpringBootElasticsearch1ApplicationTests {

    @Autowired
    private IRestHighLevelClientService iRestHighLevelClientService;

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

在这里插入图片描述

1.8.11 查询操作1

package com.example.springbootelasticsearch1;

import com.example.springbootelasticsearch1.service.IRestHighLevelClientService;
import org.elasticsearch.action.search.SearchResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
class SpringBootElasticsearch1ApplicationTests {

    @Autowired
    private IRestHighLevelClientService iRestHighLevelClientService;

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

在这里插入图片描述

1.8.12 查询操作2

package com.example.springbootelasticsearch1;

import com.example.springbootelasticsearch1.service.IRestHighLevelClientService;
import org.elasticsearch.action.search.SearchResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
class SpringBootElasticsearch1ApplicationTests {

    @Autowired
    private IRestHighLevelClientService iRestHighLevelClientService;

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

在这里插入图片描述

1.8.13 高亮查询

package com.example.springbootelasticsearch1;

import com.example.springbootelasticsearch1.service.IRestHighLevelClientService;
import org.elasticsearch.action.search.SearchResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
class SpringBootElasticsearch1ApplicationTests {

    @Autowired
    private IRestHighLevelClientService iRestHighLevelClientService;

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

在这里插入图片描述

1.9 自定义查询

  • matchQuery:词条匹配,先分词然后在调用termQuery进行匹配

  • termQuery:词条匹配,不分词

  • wildcardQuery:通配符匹配

  • fuzzyQuery:模糊匹配

  • rangeQuery:范围匹配

  • booleanQuery:布尔查询

match query (词条匹配,先分词然后在调用termQuery进行匹配)

String indexName = "student";
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("title", "小米手机"));
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

termQuery (词条匹配,不分词)

String indexName = "student";
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.termQuery("title", "小米"));
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

fuzzyQuery (模糊匹配)

String indexName = "student";
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.fuzzyQuery("title", "小米"));
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

booleanQuery (布尔查询)

BooleanClause用于表示布尔查询子句关系的类,包括:BooleanClause.Occur.MUST

BooleanClause.Occur.MUST_NOTBooleanClause.Occur.SHOULD

必须包含,不能包含,可以包含三种。

有以下6种组合:

1.MUSTMUST:交集。

2.MUSTMUST_NOT:表示查询结果中不能包含MUST_NOT所对应得查询子句的检索结果。

3.SHOULDMUST_NOT:连用时,功能同MUST和MUST_NOT。

4.SHOULDMUST连用时,结果为MUST子句的检索结果,但是SHOULD可影响排序。

5.SHOULD与SHOULD:并集。

6.MUST_NOTMUST_NOT:无意义,检索无结果。

String indexName = "student";
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("title", "手机")).must(QueryBuilders.termQuery("brand", "小米")));searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

RangeQuery 范围查找

String indexName = "student";
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.rangeQuery("price").from(3000).to(4000));
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

wildcardQuery 通配符匹配

String indexName = "student";
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.wildcardQuery("title", "%小米%"));
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

2、spring-boot-starter-data-elasticsearch方式

使用ElasticsearchRepository进行操作,ElasticSearchRepository方式主要通过注解和对接口实现的方式

来实现ES的操作,我们在实体类上通过注解配置ES索引的映射关系后,当实现了ElasticSearchRepository接口的

类第一次操作ES进行插入文档的时候,ES会自动生成所需要的一切。但是该种方式无法实现高亮查询,想要实现

高亮查询只能使用RestHighLevelClient

想要使用高版本,在创建实体的@Document属性中不可以加入type = "_doc"

2.1 导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.5.6</version>
		<relativePath/>
	</parent>
	<groupId>com.example</groupId>
	<artifactId>spring-boot-elasticsearch2</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-boot-elasticsearch2</name>
	<description>spring-boot-elasticsearch2</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>

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

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

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

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

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

2.2 配置类和配置文件

package com.example.springbootelasticsearch2.config;

import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;

@Configuration
public class EsConfig extends AbstractElasticsearchConfiguration {

    @Value("${elasticsearch.hostname}")
    private String hostname;

    @Value("${elasticsearch.port}")
    private int port;

    @Override
    @Bean
    public RestHighLevelClient elasticsearchClient() {
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder().
                connectedTo(hostname + ":" + port).build();
        return RestClients.create(clientConfiguration).rest();
    }
}
# es配置
elasticsearch.hostname=127.0.0.1
elasticsearch.port=9200

# 默认配置,在本地启动的时候可以不配置
# spring.elasticsearch.rest.uris=http://127.0.0.1:9200

2.3 创建实体类

package com.example.springbootelasticsearch2.entity;

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.util.Date;

@Document(indexName = "book", createIndex = true)
public class Book {

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

    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String title;

    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String author;

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

    @Field(type = FieldType.Date, format = DateFormat.basic_date_time)
    private Date createTime;

    @Field(type = FieldType.Date, format = DateFormat.basic_date_time)
    private Date updateTime;

    public Book() {
    }

    public Book(String id, String title, String author, Double price, Date createTime, Date updateTime) {
        this.id = id;
        this.title = title;
        this.author = author;
        this.price = price;
        this.createTime = createTime;
        this.updateTime = updateTime;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
}

createIndex = true:无需手动创建Book索引,SpringBoot启动自动创建。

@Document: 作用在类,标记实体类为文档对象,一般有四个属性:

  • indexName:对应索引库名称
  • shards:分片数量,默认5
  • replicas:副本数量,默认1
  • type:用来指定索引类型,7.x以后的版本移除了

@Id:作用在成员变量,标记一个字段作为id主键,用来将对象中id和ES中_id映射。

@Field:作用在成员变量,标记为文档的字段,并指定字段映射属性:

  • type:字段类型,取值是枚举:FieldType,具体的数据类型有:text、keyword、long、short、

    date、integer、object、byte、double、float、half_float、scaled_float

  • index:是否索引,布尔类型,默认是true

  • store:是否存储,布尔类型,默认是false

  • analyzer:分词器名称,用来指定使用哪种分词器

  • format:时间格式

  • fielddata:聚类的时候使用

@Transient:默认情况下,存储或检索文档时,所有字段都映射到文档,此注释不包括该字段。

2.4 创建Repository仓库

package com.example.springbootelasticsearch2.repository;

import com.example.springbootelasticsearch2.entity.Book;
import org.springframework.data.elasticsearch.annotations.Highlight;
import org.springframework.data.elasticsearch.annotations.HighlightField;
import org.springframework.data.elasticsearch.annotations.Query;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.util.List;

public interface ESBookRepository extends ElasticsearchRepository<Book, String> {

    List<Book> findByTitleOrAuthor(String title, String author);

    @Highlight(fields = {
            @HighlightField(name = "title"),
            @HighlightField(name = "author")
    })
    @Query("{\"match\":{\"title\":\"?0\"}}")
    SearchHits<Book> find(String keyword);
}

2.5 Service

package com.example.springbootelasticsearch2.service;

public interface BookService {
}
package com.example.springbootelasticsearch2.service.impl;

import com.example.springbootelasticsearch2.repository.ESBookRepository;
import com.example.springbootelasticsearch2.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Service;

@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private ESBookRepository esBookRepository;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
}

2.6 测试类

package com.example.springbootelasticsearch2;

import com.example.springbootelasticsearch2.entity.Book;
import com.example.springbootelasticsearch2.repository.ESBookRepository;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

@SpringBootTest
class SpringBootElasticsearch2ApplicationTests {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ESBookRepository esBookRepository;

    /**
     * 创建索引
     */
    @Test
    public void testCreateIndex() {
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(Book.class);
        Document mapping = indexOperations.createMapping();
        indexOperations.putMapping(mapping);
    }

    /**
     * 删除索引
     */
    @Test
    public void testDeleteIndex() {
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(Book.class);
        indexOperations.delete();
    }

    /**
     * 索引是否存在
     */
    @Test
    public void testExistsIndex() {
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(Book.class);
        indexOperations.exists();
    }

    /**
     * 新增文档
     */
    @Test
    void addDocument() {
        Book book1 = new Book("1", "《西游记》", "吴承恩", 49.9, new Date(), new Date());
        esBookRepository.save(book1);
        Book book2 = new Book("2", "《红楼梦》", "曹雪芹", 59.9, new Date(), new Date());
        esBookRepository.save(book2);
        Book book3 = new Book("3", "《三国演义》", "罗贯中", 39.9, new Date(), new Date());
        esBookRepository.save(book3);
        Book book4 = new Book("4", "《水浒传》", "施耐庵", 69.9, new Date(), new Date());
        esBookRepository.save(book4);
    }

    /**
     * 一次新增多条文档
     */
    @Test
    public void addManyDocument() {
        List<Book> books = new ArrayList<Book>();
        Book book1 = new Book("1", "《西游记》", "吴承恩", 49.9, new Date(), new Date());
        Book book2 = new Book("2", "《红楼梦》", "曹雪芹", 59.9, new Date(), new Date());
        Book book3 = new Book("3", "《三国演义》", "罗贯中", 39.9, new Date(), new Date());
        Book book4 = new Book("4", "《水浒传》", "施耐庵", 69.9, new Date(), new Date());
        books.add(book1);
        books.add(book2);
        books.add(book3);
        books.add(book4);
        esBookRepository.saveAll(books);
    }

    /**
     * 判断某id的文档是否存在
     */
    @Test
    void documentExist() {
        boolean exists = esBookRepository.existsById("2");
        System.out.println(exists);
    }

    /**
     * 修改文档
     */
    @Test
    void updateDocument() {
        Book book = new Book("1", "《西游记》", "吴承恩", 149.9, new Date(), new Date());
        esBookRepository.save(book);
    }

    /**
     * 删除文档
     */
    @Test
    void deleteDocument() {
        esBookRepository.deleteById("1");
    }

    /**
     * 删除所有文档
     */
    @Test
    void deleteAllDocument() {
        esBookRepository.deleteAll();
    }

    /**
     * 根据id查询文档
     */
    @Test
    void queryDocumentByID() {
        Optional<Book> book = esBookRepository.findById("1");
        System.out.println(book.get());
    }

    /**
     * 查询所有文档
     */
    @Test
    void queryAllDocument() {
        Iterable<Book> all = esBookRepository.findAll();
        all.forEach(System.out::println);
    }

    /**
     * 排序文档
     */
    @Test
    void sortAllDocument() {
        Iterable<Book> all = esBookRepository.findAll(Sort.by(Sort.Order.asc("price")));
        all.forEach(System.out::println);
    }

    // 分页
    @Test
    void pageDocument() {
        // SpringBoot2.5.6已经移除了ElasticsearchRepository里的search()方法,只剩了一些特别基础的增删改查,基本上是不能用的。
        // 官方明显是想让开发者用ElasticsearchRestTemplate去做。
        MatchAllQueryBuilder matchQueryBuilder = QueryBuilders.matchAllQuery();
        NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(matchQueryBuilder);
        nativeSearchQuery.setPageable(PageRequest.of(2, 1));
        SearchHits<Book> search = elasticsearchRestTemplate.search(nativeSearchQuery, Book.class);
        for (SearchHit<Book> hit : search.getSearchHits()) {
            System.out.println(hit.getContent().getTitle());
        }
    }

    // 自定义查询
    @Test
    void query1() {
        List<Book> book = esBookRepository.findByTitleOrAuthor("《红楼梦》", "曹雪芹");
        book.forEach(System.out::println);
    }

    // 自定义json规则查询
    @Test
    void query2() {
        SearchHits<Book> book = esBookRepository.find("《红楼梦》");
        // SearchHit{id='2', score=3.1789374, sortValues=[], content=com.example.springbootelasticsearch2.entity.Book@48cb2d73,
        // highlightFields={title=[《<em>红楼梦</em>》]}}
        book.forEach(System.out::println);
    }

}

2.7 启动类

package com.example.springbootelasticsearch2;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootElasticsearch2Application {

	public static void main(String[] args) {

		SpringApplication.run(SpringBootElasticsearch2Application.class, args);
	}

}

2.8 测试

2.8.1 新建索引

package com.example.springbootelasticsearch2;

import com.example.springbootelasticsearch2.entity.Book;
import com.example.springbootelasticsearch2.repository.ESBookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.document.Document;

@SpringBootTest
class SpringBootElasticsearch2ApplicationTests {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ESBookRepository esBookRepository;

    /**
     * 创建索引
     */
    @Test
    public void testCreateIndex() {
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(Book.class);
        Document mapping = indexOperations.createMapping();
        indexOperations.putMapping(mapping);
    }
}

在这里插入图片描述

在这里插入图片描述

2.8.2 删除索引

package com.example.springbootelasticsearch2;

import com.example.springbootelasticsearch2.entity.Book;
import com.example.springbootelasticsearch2.repository.ESBookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;

@SpringBootTest
class SpringBootElasticsearch2ApplicationTests {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ESBookRepository esBookRepository;

    /**
     * 删除索引
     */
    @Test
    public void testDeleteIndex() {
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(Book.class);
        indexOperations.delete();
    }
}

在这里插入图片描述

2.8.3 索引是否存在

package com.example.springbootelasticsearch2;

import com.example.springbootelasticsearch2.entity.Book;
import com.example.springbootelasticsearch2.repository.ESBookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;

@SpringBootTest
class SpringBootElasticsearch2ApplicationTests {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ESBookRepository esBookRepository;

    /**
     * 索引是否存在
     */
    @Test
    public void testExistsIndex() {
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(Book.class);
        indexOperations.exists();
    }
}

在这里插入图片描述

2.8.4 新增文档

package com.example.springbootelasticsearch2;

import com.example.springbootelasticsearch2.entity.Book;
import com.example.springbootelasticsearch2.repository.ESBookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;

import java.util.Date;

@SpringBootTest
class SpringBootElasticsearch2ApplicationTests {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ESBookRepository esBookRepository;

    /**
     * 新增文档
     */
    @Test
    void addDocument() {
        Book book1 = new Book("1", "《西游记》", "吴承恩", 49.9, new Date(), new Date());
        esBookRepository.save(book1);
        Book book2 = new Book("2", "《红楼梦》", "曹雪芹", 59.9, new Date(), new Date());
        esBookRepository.save(book2);
        Book book3 = new Book("3", "《三国演义》", "罗贯中", 39.9, new Date(), new Date());
        esBookRepository.save(book3);
        Book book4 = new Book("4", "《水浒传》", "施耐庵", 69.9, new Date(), new Date());
        esBookRepository.save(book4);
    }
}

在这里插入图片描述

在这里插入图片描述

2.8.5 判断某id的文档是否存在

package com.example.springbootelasticsearch2;

import com.example.springbootelasticsearch2.repository.ESBookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;

@SpringBootTest
class SpringBootElasticsearch2ApplicationTests {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ESBookRepository esBookRepository;

    /**
     * 判断某id的文档是否存在
     */
    @Test
    void documentExist() {
        boolean exists = esBookRepository.existsById("2");
        System.out.println(exists);
    }

}

在这里插入图片描述

2.8.6 修改文档

package com.example.springbootelasticsearch2;

import com.example.springbootelasticsearch2.entity.Book;
import com.example.springbootelasticsearch2.repository.ESBookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;

import java.util.Date;

@SpringBootTest
class SpringBootElasticsearch2ApplicationTests {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ESBookRepository esBookRepository;

    /**
     * 修改文档
     */
    @Test
    void updateDocument() {
        Book book = new Book("1", "《西游记》", "吴承恩", 149.9, new Date(), new Date());
        esBookRepository.save(book);
    }
}

在这里插入图片描述

在这里插入图片描述

2.8.7 删除文档

package com.example.springbootelasticsearch2;

import com.example.springbootelasticsearch2.repository.ESBookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;

@SpringBootTest
class SpringBootElasticsearch2ApplicationTests {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ESBookRepository esBookRepository;

    /**
     * 删除文档
     */
    @Test
    void deleteDocument() {
        esBookRepository.deleteById("1");
    }
}

在这里插入图片描述

2.8.8 刪除所有文档

package com.example.springbootelasticsearch2;

import com.example.springbootelasticsearch2.repository.ESBookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;

@SpringBootTest
class SpringBootElasticsearch2ApplicationTests {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ESBookRepository esBookRepository;

    /**
     * 删除所有文档
     */
    @Test
    void deleteAllDocument() {
        esBookRepository.deleteAll();
    }

}

在这里插入图片描述

在这里插入图片描述

2.8.9 一次新增多条文档

package com.example.springbootelasticsearch2;

import com.example.springbootelasticsearch2.entity.Book;
import com.example.springbootelasticsearch2.repository.ESBookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@SpringBootTest
class SpringBootElasticsearch2ApplicationTests {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ESBookRepository esBookRepository;

    /**
     * 一次新增多条文档
     */
    @Test
    public void addManyDocument() {
        List<Book> books = new ArrayList<Book>();
        Book book1 = new Book("1", "《西游记》", "吴承恩", 49.9, new Date(), new Date());
        Book book2 = new Book("2", "《红楼梦》", "曹雪芹", 59.9, new Date(), new Date());
        Book book3 = new Book("3", "《三国演义》", "罗贯中", 39.9, new Date(), new Date());
        Book book4 = new Book("4", "《水浒传》", "施耐庵", 69.9, new Date(), new Date());
        books.add(book1);
        books.add(book2);
        books.add(book3);
        books.add(book4);
        esBookRepository.saveAll(books);
    }

}

在这里插入图片描述

在这里插入图片描述

2.8.10 根据id查询文档

package com.example.springbootelasticsearch2;

import com.example.springbootelasticsearch2.entity.Book;
import com.example.springbootelasticsearch2.repository.ESBookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;

import java.util.Optional;

@SpringBootTest
class SpringBootElasticsearch2ApplicationTests {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ESBookRepository esBookRepository;

    /**
     * 根据id查询文档
     */
    @Test
    void queryDocumentByID() {
        Optional<Book> book = esBookRepository.findById("2");
        System.out.println(book.get());
    }
}

在这里插入图片描述

2.8.11 查询所有文档

package com.example.springbootelasticsearch2;

import com.example.springbootelasticsearch2.entity.Book;
import com.example.springbootelasticsearch2.repository.ESBookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;

import java.util.Optional;

@SpringBootTest
class SpringBootElasticsearch2ApplicationTests {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ESBookRepository esBookRepository;

    /**
     * 查询所有文档
     */
    @Test
    void queryAllDocument() {
        Iterable<Book> all = esBookRepository.findAll();
        all.forEach(System.out::println);
    }
}

在这里插入图片描述

2.8.12 排序文档

package com.example.springbootelasticsearch2;

import com.example.springbootelasticsearch2.entity.Book;
import com.example.springbootelasticsearch2.repository.ESBookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;

@SpringBootTest
class SpringBootElasticsearch2ApplicationTests {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ESBookRepository esBookRepository;

    /**
     * 排序文档
     */
    @Test
    void sortAllDocument() {
        Iterable<Book> all = esBookRepository.findAll(Sort.by(Sort.Order.asc("price")));
        all.forEach(System.out::println);
    }

}

在这里插入图片描述

2.8.13 分页

package com.example.springbootelasticsearch2;

import com.example.springbootelasticsearch2.entity.Book;
import com.example.springbootelasticsearch2.repository.ESBookRepository;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;

@SpringBootTest
class SpringBootElasticsearch2ApplicationTests {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ESBookRepository esBookRepository;

    // 分页
    @Test
    void pageDocument() {
        // SpringBoot2.5.6已经移除了ElasticsearchRepository里的search()方法,只剩了一些特别基础的增删改查,基本上是不能用的。
        // 官方明显是想让开发者用ElasticsearchRestTemplate去做。
        MatchAllQueryBuilder matchQueryBuilder = QueryBuilders.matchAllQuery();
        NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(matchQueryBuilder);
        nativeSearchQuery.setPageable(PageRequest.of(2, 1));
        SearchHits<Book> search = elasticsearchRestTemplate.search(nativeSearchQuery, Book.class);
        for (SearchHit<Book> hit : search.getSearchHits()) {
            System.out.println(hit.getContent().getTitle());
        }
    }

}

在这里插入图片描述

2.8.14 自定义查询

package com.example.springbootelasticsearch2;

import com.example.springbootelasticsearch2.entity.Book;
import com.example.springbootelasticsearch2.repository.ESBookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;

import java.util.List;

@SpringBootTest
class SpringBootElasticsearch2ApplicationTests {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ESBookRepository esBookRepository;

    // 自定义查询
    @Test
    void query1() {
        List<Book> book = esBookRepository.findByTitleOrAuthor("《红楼梦》", "曹雪芹");
        book.forEach(System.out::println);
    }

}

在这里插入图片描述

2.8.15 自定义json规则查询

package com.example.springbootelasticsearch2;

import com.example.springbootelasticsearch2.entity.Book;
import com.example.springbootelasticsearch2.repository.ESBookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;

@SpringBootTest
class SpringBootElasticsearch2ApplicationTests {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ESBookRepository esBookRepository;

    // 自定义json规则查询
    @Test
    void query2() {
        SearchHits<Book> book = esBookRepository.find("《红楼梦》");
        // SearchHit{id='2', score=3.1789374, sortValues=[], content=com.example.springbootelasticsearch2.entity.Book@48cb2d73, 
        // highlightFields={title=[《<em>红楼梦</em>》]}}
        book.forEach(System.out::println);
    }

}

在这里插入图片描述

2.9 自定义查询规则

KeywordSampleElasticsearch Query String
AndfindByNameAndPrice{"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
OrfindByNameOrPrice{"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
IsfindByName{"bool" : {"must" : {"field" : {"name" : "?"}}}}
NotfindByNameNot{"bool" : {"must_not" : {"field" : {"name" : "?"}}}}
BetweenfindByPriceBetween{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
LessThanEqualfindByPriceLessThan{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
GreaterThanEqualfindByPriceGreaterThan{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
BeforefindByPriceBefore{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
AfterfindByPriceAfter{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
LikefindByNameLike{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
StartingWithfindByNameStartingWith{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
EndingWithfindByNameEndingWith{"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}}
Contains/ContainingfindByNameContaining{"bool" : {"must" : {"field" : {"name" : {"query" : "**?**","analyze_wildcard" : true}}}}}
InfindByNameIn (Collection<String>names){"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}
NotInfindByNameNotIn (Collection<String>names){"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}}
NearfindByStoreNearNot Supported Yet !
TruefindByAvailableTrue{"bool" : {"must" : {"field" : {"available" : true}}}}
FalsefindByAvailableFalse{"bool" : {"must" : {"field" : {"available" : false}}}}
OrderByfindByAvailable TrueOrderByNameDesc{"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}}

我们只要按照上面的定义在接口中定义相应的方法,无须写实现就可实现我们想要的功能。

系统提供的查询方法中findBy是一个固定写法,像上面我们定义的方法findByTitle,其中Title是我们实体

类中的属性名,这个必须对应上。findByTitle是下面这样定义的:

{"bool" : {"must" : {"field" : {"title" : "?"}}}}

假如我们现在有个需求需要按照作者查询书籍,我们可以在BookRepository中定义一个方法,如下:

// 根据作者查询书籍
List<User> findByAuthor(String author);

那么我们可以使用该方法:

@Test
public void testFindBookByAuthor(){
    List<Book> bookList = bookRepository.findByAuthor("曹雪芹");
    bookList.forEach(System.out::println);
}

其实就是框架底层直接使用下面的命令帮我们实现的查询:

GET /book/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "author":"曹雪芹"
          }
        }
      ]
    }
  }
}

在这里插入图片描述

ElasticSearchRepository实现不了高亮查询,想要实现高亮查询还是需要使用RestHighLevelClient方式。

3、transport方式(7.x开始弃用)

使用TransportClient进行操作

3.1 导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.5.6</version>
		<relativePath/>
	</parent>

	<groupId>com.example</groupId>
	<artifactId>spring-boot-elasticsearch3</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-boot-elasticsearch3</name>
	<description>spring-boot-elasticsearch3</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>

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

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.elasticsearch.client</groupId>
			<artifactId>transport</artifactId>
			<version>7.12.1</version>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
		</dependency>

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.58</version>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

3.2 配置文件

elasticsearch.cluster-name = elasticsearch
elasticsearch.ip = 127.0.0.1
elasticsearch.port = 9300
elasticsearch.pool = 5

3.3 创建配置类

package com.example.springbootelasticsearch3.config;

import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.net.InetAddress;

/**
 * @author zhangshixing
 * @date 2021年11月11日 12:28
 */
@Slf4j
@Configuration
public class ElasticSearchConfig {

    @Value("${elasticsearch.ip}")
    private String hostName;

    /**
     * 端口
     */
    @Value("${elasticsearch.port}")
    private String port;

    /**
     * 集群名称
     */
    @Value("${elasticsearch.cluster-name}")
    private String clusterName;

    /**
     * 连接池
     */
    @Value("${elasticsearch.pool}")
    private String poolSize;

    /**
     * Bean name default  函数名字
     *
     * @return
     */
    @Bean(name = "transportClient")
    public TransportClient transportClient() {
        log.info("Elasticsearch初始化开始。。。。。");
        TransportClient transportClient = null;
        try {
            // 配置信息
            Settings esSetting = Settings.builder()
                    //集群名字
                    .put("cluster.name", clusterName)
                    //增加嗅探机制,找到ES集群
                    .put("client.transport.sniff", true)
                    //增加线程池个数,暂时设为5
                    .put("thread_pool.search.size", Integer.parseInt(poolSize))
                    .build();
            //配置信息Settings自定义
            transportClient = new PreBuiltTransportClient(esSetting);
            TransportAddress transportAddress = new TransportAddress(InetAddress.getByName(hostName), Integer.valueOf(port));
            transportClient.addTransportAddresses(transportAddress);
        } catch (Exception e) {
            log.error("elasticsearch TransportClient create error!!", e);
        }
        return transportClient;
    }
}

3.4 创建工具类

package com.example.springbootelasticsearch3.utils;

import java.util.List;
import java.util.Map;

/**
 * @author zhangshixing
 * @date 2021年11月11日 12:42
 */
public class EsPage {

    /**
     * 当前页
     */
    private int currentPage;
    /**
     * 每页显示多少条
     */
    private int pageSize;

    /**
     * 总记录数
     */
    private int recordCount;
    /**
     * 本页的数据列表
     */
    private List<Map<String, Object>> recordList;

    /**
     * 总页数
     */
    private int pageCount;
    /**
     * 页码列表的开始索引(包含)
     */
    private int beginPageIndex;
    /**
     * 页码列表的结束索引(包含)
     */
    private int endPageIndex;

    /**
     * 只接受前4个必要的属性,会自动的计算出其他3个属性的值
     *
     * @param currentPage
     * @param pageSize
     * @param recordCount
     * @param recordList
     */
    public EsPage(int currentPage, int pageSize, int recordCount, List<Map<String, Object>> recordList) {
        this.currentPage = currentPage;
        this.pageSize = pageSize;
        this.recordCount = recordCount;
        this.recordList = recordList;

        // 计算总页码
        pageCount = (recordCount + pageSize - 1) / pageSize;

        // 计算 beginPageIndex 和 endPageIndex
        // >> 总页数不多于10页,则全部显示
        if (pageCount <= 10) {
            beginPageIndex = 1;
            endPageIndex = pageCount;
        }
        // >> 总页数多于10页,则显示当前页附近的共10个页码
        else {
            // 当前页附近的共10个页码(前4个 + 当前页 + 后5个)
            beginPageIndex = currentPage - 4;
            endPageIndex = currentPage + 5;
            // 当前面的页码不足4个时,则显示前10个页码
            if (beginPageIndex < 1) {
                beginPageIndex = 1;
                endPageIndex = 10;
            }
            // 当后面的页码不足5个时,则显示后10个页码
            if (endPageIndex > pageCount) {
                endPageIndex = pageCount;
                beginPageIndex = pageCount - 10 + 1;
            }
        }
    }


    public int getCurrentPage() {
        return currentPage;
    }

    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public int getRecordCount() {
        return recordCount;
    }

    public void setRecordCount(int recordCount) {
        this.recordCount = recordCount;
    }

    public List<Map<String, Object>> getRecordList() {
        return recordList;
    }

    public void setRecordList(List<Map<String, Object>> recordList) {
        this.recordList = recordList;
    }

    public int getPageCount() {
        return pageCount;
    }

    public void setPageCount(int pageCount) {
        this.pageCount = pageCount;
    }

    public int getBeginPageIndex() {
        return beginPageIndex;
    }

    public void setBeginPageIndex(int beginPageIndex) {
        this.beginPageIndex = beginPageIndex;
    }

    public int getEndPageIndex() {
        return endPageIndex;
    }

    public void setEndPageIndex(int endPageIndex) {
        this.endPageIndex = endPageIndex;
    }

}
package com.example.springbootelasticsearch3.utils;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequestBuilder;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;


/**
 * @author zhangshixing
 * @date 2021年11月11日 12:39
 */
@Component
@Slf4j
public class ElasticsearchUtil {

    @Autowired
    private TransportClient transportClient;

    private static TransportClient client;

    /**
     * @PostContruct是spring框架的注解 spring容器初始化的时候执行该方法
     */
    @PostConstruct
    public void init() {
        client = this.transportClient;
    }

    /**
     * 创建索引
     *
     * @param index
     * @return
     */
    public static boolean createIndex(String index) {
        if (!isIndexExist(index)) {
            log.info("Index is not exits!");
        }
        CreateIndexResponse indexResponse = client.admin().indices().prepareCreate(index).execute().actionGet();
        log.info("执行建立成功?" + indexResponse.isAcknowledged());
        return indexResponse.isAcknowledged();
    }

    /**
     * 删除索引
     *
     * @param index
     * @return
     */
    public static boolean deleteIndex(String index) {
        if (!isIndexExist(index)) {
            log.info("Index is not exits!");
        }
        AcknowledgedResponse dResponse = client.admin().indices().prepareDelete(index).execute().actionGet();
        if (dResponse.isAcknowledged()) {
            log.info("delete index " + index + "  successfully!");
        } else {
            log.info("Fail to delete index " + index);
        }
        return dResponse.isAcknowledged();
    }

    /**
     * 判断索引是否存在
     *
     * @param index
     * @return
     */
    public static boolean isIndexExist(String index) {
        IndicesExistsResponse inExistsResponse = client.admin().indices().exists(new IndicesExistsRequest(index)).actionGet();
        if (inExistsResponse.isExists()) {
            log.info("Index [" + index + "] is exist!");
        } else {
            log.info("Index [" + index + "] is not exist!");
        }
        return inExistsResponse.isExists();
    }

    /**
     * 数据添加,正定ID
     *
     * @param jsonObject 要增加的数据
     * @param index      索引,类似数据库
     * @param type       类型,类似表
     * @param id         数据ID
     * @return
     */
    public static String addData(JSONObject jsonObject, String index, String type, String id) {
        IndexResponse response = client.prepareIndex(index, type, id).setSource(jsonObject).get();
        log.info("addData response status:{},id:{}", response.status().getStatus(), response.getId());
        return response.getId();
    }

    /**
     * 数据添加
     *
     * @param jsonObject 要增加的数据
     * @param index      索引,类似数据库
     * @param type       类型,类似表
     * @return
     */
    public static String addData(JSONObject jsonObject, String index, String type) {
        return addData(jsonObject, index, type, UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
    }

    /**
     * 通过ID删除数据
     *
     * @param index 索引,类似数据库
     * @param type  类型,类似表
     * @param id    数据ID
     */
    public static void deleteDataById(String index, String type, String id) {
        DeleteResponse response = client.prepareDelete(index, type, id).execute().actionGet();
        log.info("deleteDataById response status:{},id:{}", response.status().getStatus(), response.getId());
    }

    /**
     * 通过ID 更新数据
     *
     * @param jsonObject 要增加的数据
     * @param index      索引,类似数据库
     * @param type       类型,类似表
     * @param id         数据ID
     * @return
     */
    public static void updateDataById(JSONObject jsonObject, String index, String type, String id) {
        UpdateRequest updateRequest = new UpdateRequest();
        updateRequest.index(index).type(type).id(id).doc(jsonObject);
        client.update(updateRequest);
    }

    /**
     * 通过ID获取数据
     *
     * @param index  索引,类似数据库
     * @param type   类型,类似表
     * @param id     数据ID
     * @param fields 需要显示的字段,逗号分隔(缺省为全部字段)
     * @return
     */
    public static Map<String, Object> searchDataById(String index, String type, String id, String fields) {
        GetRequestBuilder getRequestBuilder = client.prepareGet(index, type, id);
        if (StringUtils.isNotEmpty(fields)) {
            getRequestBuilder.setFetchSource(fields.split(","), null);
        }
        GetResponse getResponse = getRequestBuilder.execute().actionGet();
        return getResponse.getSource();
    }

    /**
     * 使用分词查询,并分页
     *
     * @param index          索引名称
     * @param type           类型名称,可传入多个type逗号分隔
     * @param startPage      当前页
     * @param pageSize       每页显示条数
     * @param query          查询条件
     * @param fields         需要显示的字段,逗号分隔(缺省为全部字段)
     * @param sortField      排序字段
     * @param highlightField 高亮字段
     * @return
     */
    public static EsPage searchDataPage(String index, String type, int startPage, int pageSize, QueryBuilder query, String fields, String sortField, String highlightField) {
        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
        if (StringUtils.isNotEmpty(type)) {
            searchRequestBuilder.setTypes(type.split(","));
        }
        searchRequestBuilder.setSearchType(SearchType.QUERY_THEN_FETCH);
        // 需要显示的字段,逗号分隔(缺省为全部字段)
        if (StringUtils.isNotEmpty(fields)) {
            searchRequestBuilder.setFetchSource(fields.split(","), null);
        }

        //排序字段
        if (StringUtils.isNotEmpty(sortField)) {
            searchRequestBuilder.addSort(sortField, SortOrder.DESC);
        }

        // 高亮(xxx=111,aaa=222)
        if (StringUtils.isNotEmpty(highlightField)) {
            HighlightBuilder highlightBuilder = new HighlightBuilder();

            //highlightBuilder.preTags("<span style='color:red' >");//设置前缀
            //highlightBuilder.postTags("</span>");//设置后缀

            // 设置高亮字段
            highlightBuilder.field(highlightField);
            searchRequestBuilder.highlighter(highlightBuilder);
        }

        //searchRequestBuilder.setQuery(QueryBuilders.matchAllQuery());
        searchRequestBuilder.setQuery(query);

        // 分页应用
        searchRequestBuilder.setFrom(startPage).setSize(pageSize);

        // 设置是否按查询匹配度排序
        searchRequestBuilder.setExplain(true);

        //打印的内容 可以在 Elasticsearch head 和 Kibana  上执行查询
        log.info("\n{}", searchRequestBuilder);

        // 执行搜索,返回搜索响应信息
        SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();

        TotalHits totalHits = searchResponse.getHits().getTotalHits();
        long length = searchResponse.getHits().getHits().length;

        log.debug("共查询到[{}]条数据,处理数据条数[{}]", totalHits.value, length);

        if (searchResponse.status().getStatus() == 200) {
            // 解析对象
            List<Map<String, Object>> sourceList = setSearchResponse(searchResponse, highlightField);

            return new EsPage(startPage, pageSize, (int) totalHits.value, sourceList);
        }

        return null;

    }

    /**
     * 使用分词查询
     *
     * @param index          索引名称
     * @param type           类型名称,可传入多个type逗号分隔
     * @param query          查询条件
     * @param size           文档大小限制
     * @param fields         需要显示的字段,逗号分隔(缺省为全部字段)
     * @param sortField      排序字段
     * @param highlightField 高亮字段
     * @return
     */
    public static List<Map<String, Object>> searchListData(String index, String type, QueryBuilder query, Integer size, String fields, String sortField, String highlightField) {

        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
        if (StringUtils.isNotEmpty(type)) {
            searchRequestBuilder.setTypes(type.split(","));
        }

        if (StringUtils.isNotEmpty(highlightField)) {
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            // 设置高亮字段
            highlightBuilder.field(highlightField);
            searchRequestBuilder.highlighter(highlightBuilder);
        }

        searchRequestBuilder.setQuery(query);

        if (StringUtils.isNotEmpty(fields)) {
            searchRequestBuilder.setFetchSource(fields.split(","), null);
        }
        searchRequestBuilder.setFetchSource(true);

        if (StringUtils.isNotEmpty(sortField)) {
            searchRequestBuilder.addSort(sortField, SortOrder.DESC);
        }

        if (size != null && size > 0) {
            searchRequestBuilder.setSize(size);
        }

        //打印的内容 可以在 Elasticsearch head 和 Kibana  上执行查询
        log.info("\n{}", searchRequestBuilder);

        SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();

        TotalHits totalHits = searchResponse.getHits().getTotalHits();
        long length = searchResponse.getHits().getHits().length;

        log.info("共查询到[{}]条数据,处理数据条数[{}]", totalHits.value, length);

        if (searchResponse.status().getStatus() == 200) {
            // 解析对象
            return setSearchResponse(searchResponse, highlightField);
        }

        return null;

    }


    /**
     * 高亮结果集 特殊处理
     *
     * @param searchResponse
     * @param highlightField
     */
    private static List<Map<String, Object>> setSearchResponse(SearchResponse searchResponse, String highlightField) {
        List<Map<String, Object>> sourceList = new ArrayList<Map<String, Object>>();
        StringBuffer stringBuffer = new StringBuffer();

        for (SearchHit searchHit : searchResponse.getHits().getHits()) {
            searchHit.getSourceAsMap().put("id", searchHit.getId());

            if (StringUtils.isNotEmpty(highlightField)) {

                System.out.println("遍历 高亮结果集,覆盖 正常结果集" + searchHit.getSourceAsMap());
                Text[] text = searchHit.getHighlightFields().get(highlightField).getFragments();

                if (text != null) {
                    for (Text str : text) {
                        stringBuffer.append(str.string());
                    }
                    //遍历 高亮结果集,覆盖 正常结果集
                    searchHit.getSourceAsMap().put(highlightField, stringBuffer.toString());
                }
            }
            sourceList.add(searchHit.getSourceAsMap());
        }

        return sourceList;
    }
}

3.5 启动类

package com.example.springbootelasticsearch3;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootElasticsearch3Application {

    public static void main(String[] args) {

        SpringApplication.run(SpringBootElasticsearch3Application.class, args);
    }

}

3.6 测试类

package com.example.springbootelasticsearch3;

import com.alibaba.fastjson.JSONObject;
import com.example.springbootelasticsearch3.utils.ElasticsearchUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.DateUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * @author zhangshixing
 * @date 2021年11月11日 12:43
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class GoodsResiportyTest {

    /**
     * 类型
     */
    private String esType = "external";
    /**
     * 索引
     */
    private String indexName = "test_index";

    /**
     * 创建索引
     */
    @Test
    public void createIndex() {
        if (!ElasticsearchUtil.isIndexExist(indexName)) {
            ElasticsearchUtil.createIndex(indexName);
        } else {
            System.out.print("索引已经存在");
        }
        System.out.print("索引创建成功");
    }

    /**
     * 删除索引
     */
    @Test
    public void deleteIndex() {
        if (!ElasticsearchUtil.isIndexExist(indexName)) {
            System.out.print("索引不存在");
        } else {
            ElasticsearchUtil.deleteIndex(indexName);
        }
        System.out.print("索引删除成功");
    }

    /**
     * 索引是否存在
     */
    @Test
    public void cexistsIndex() {
        if (!ElasticsearchUtil.isIndexExist(indexName)) {
            System.out.print("索引不存在");
        } else {
            System.out.print("索引存在");
        }
    }

    /**
     * 指定索引插入数据
     */
    @Test
    public void insertJson() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id", DateUtils.formatDate(new Date()));
        jsonObject.put("age", 25);
        jsonObject.put("name", "j-" + new Random(100).nextInt());
        jsonObject.put("createTime", new Date());
        String id = ElasticsearchUtil.addData(jsonObject, indexName, esType, jsonObject.getString("id"));
    }

    @Test
    public void delete() {
        String id = "12";
        if (StringUtils.isNotBlank(id)) {
            ElasticsearchUtil.deleteDataById(indexName, esType, id);
            System.out.print("删除id=" + id);
        } else {
            System.out.print("id为空");
        }
    }

    @Test
    public void queryMatchData() {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolean matchPhrase = false;
        if (matchPhrase == Boolean.TRUE) {
            boolQuery.must(QueryBuilders.matchPhraseQuery("name", "j"));
        } else {
            boolQuery.must(QueryBuilders.matchQuery("name", "j"));
        }
        List<Map<String, Object>> list = ElasticsearchUtil.searchListData(indexName, esType, boolQuery, 10, null, null, null);
        System.out.print(JSONObject.toJSONString(list));
    }
}
{"size":10,"query":{"bool":{"must":[{"match":{"name":{"query":"j","operator":"OR","prefix_length":0,"max_expansions":50,"fuzzy_transpositions":true,"lenient":false,"zero_terms_query":"NONE","auto_generate_synonyms_phrase_query":true,"boost":1.0}}}],"adjust_pure_negative":true,"boost":1.0}},"_source":{"includes":[],"excludes":[]}}
2022-06-23 10:59:36.190  INFO 18272 --- [           main] c.e.s.utils.ElasticsearchUtil            : 共查询到[1]条数据,处理数据条数[1]
[{"createTime":"2022-06-23T02:56:35.337Z","name":"j--1193959466","id":"Thu, 23 Jun 2022 02:56:35 GMT","age":25}]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/52999.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【MySQL】模具更新方案

系列文章 C#底层库–MySQLBuilder脚本构建类&#xff08;select、insert、update、in、带条件的SQL自动生成&#xff09; 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/129179216 C#底层库–MySQL数据库操作辅助类&#xff08;推荐阅读&#xff0…

简化Java单元测试数据

用EasyModeling简化Java单元测试 EasyModeling 是我在2021年圣诞假期期间开发的一个 Java 注解处理器&#xff0c;采用 Apache-2.0 开源协议。它可以帮助 Java 单元测试的编写者快速构造用于测试的数据模型实例&#xff0c;简化 Java 项目在单元测试中准备测试数据的工作&…

C++ ——STL容器【list】模拟实现

代码仓库&#xff1a; list模拟实现 list源码 数据结构——双向链表 文章目录 &#x1f347;1. 节点结构体&#x1f348;2. list成员&#x1f349;3. 迭代器模板&#x1f34a;4. 迭代器&#x1f34b;5. 插入删除操作&#x1f34c;5.1 insert & erase&#x1f34c;5.2 push_…

flask处理表单数据

flask处理表单数据 处理表单数据在任何 web 应用开发中都是一个常见的需求。在 Flask 中&#xff0c;你可以使用 request 对象来获取通过 HTTP 请求发送的数据。对于 POST 请求&#xff0c;可以通过 request.form 访问表单数据。例如&#xff1a; from flask import Flask, r…

电子鼻毕业论文

面向压埋探测的人体代谢气体识别方法的研究与应用 实现对非目标气体的检测 数据预处理 &#xff08;1a&#xff09;标准化 将采集到的数据先进行变换&#xff0c;统一数量级。其中&#xff0c;xij为第j个传感器的第i个采样值&#xff1b;xj为第 j 个气体传感器的所有采样值&…

Java课题笔记~Maven基础

2、Maven 基础 2.1 Maven安装与配置 下载安装 配置&#xff1a;修改安装目录/conf/settings.xml 本地仓库&#xff1a;存放的是下载的jar包 中央仓库&#xff1a;要从哪个网站去下载jar包 - 阿里云的仓库 2.2 创建Maven项目

计算机网络——学习笔记

付费版&#xff1a;直接在上面的CSDN资源下载 免费版&#xff1a;https://wwsk.lanzouk.com/ijkcj13tqmyb 有疑问或者错误的地方可以在评论区指出&#xff0c;我会尽快回复 示例图&#xff1a;

SOC FPGA之HPS模型设计(一)

目录 一、建立HPS硬件系统模型 1.1 GHRD 1.2 从0开始搭建HPS 1.2.1 FPGA Interfaces 1.2.1.1 General 1.2.1.2 AXI Bridge 1.2.1.3 FPGA-to-HPS SDRAM Interface 1.2.1.4 DMA Peripheral Request 1.2.1.5 Interrupts 1.2.1.6 EMAC ptp interface 1.2.2 Peripheral P…

[JAVAee]线程池

目录 线程池的作用 线程池的使用 线程池的创建方式 线程池的解析 ①Executors与ThreadPoolExecutor ②ThreadPoolExecutor线程池的构造方法 ③RejectedExecutionHandler线程池的拒绝策略 固定线程数量线程池的简单模拟实现 线程池的作用 对于线程的使用,可能会频繁的创建…

首批!棱镜七彩通过汽车云-汽车软件研发效能成熟度模型能力评估

2023年7月25-26日&#xff0c;由中国信息通信研究院、中国通信标准化协会联合主办的“2023年可信云大会”隆重召开。会上&#xff0c;在中国信息通信研究院云计算与大数据研究所副所长栗蔚的主持下&#xff0c;中国信通院发布了“2023年上半年可信云评估结果”&#xff0c;并由…

uniapp checkbox radio 样式修改

文章目录 通过查看代码&#xff0c;发现 before部分是设置样式的主要属性 我们要设置的话&#xff0c;就要设置checkbox::before的属性。 其中的content表示内容&#xff0c;比如内部的对勾 那么我们设置的时候&#xff0c;比如设置disabletrue的时候或者checkedtrue的时候&…

onnxruntime (C++/CUDA) 编译安装

一、克隆及编译 git clone --recursive https://github.com/Microsoft/onnxruntime cd onnxruntime/ git checkout v1.8.0如果克隆的时候报错&#xff1a; 执行以下&#xff1a; apt-get install gnutls-bin git config --global http.sslVerify false git config --global h…

Git初始化

查看git版本 git --version 设置Git的配置变量 方法&#xff1a; 修改全局文件&#xff08;用户主目录下.gitconfig&#xff09;修改系统文件&#xff08;如/etc/gitconfig&#xff09; 用户姓名和邮件地址 修改用户名和邮件地址 git config --global user.name "用…

《JeecgBoot系列》JeecgBoot(ant-design-vue)实现筛选框:支持下拉搜索+下拉多选+表字典(支持条件查询)功能

JeecgBoot(ant-design-vue)实现筛选框&#xff1a;支持下拉搜索下拉多选表字典(支持条件查询)功能 JSearchMultiSelectTag.vue源文件 一、需求介绍 在使用JeectBoot(ant-design-vue)设计表单时&#xff0c;需要实现下拉搜索下拉多选表字典(支持条件查询)。 但是系统目前有两…

PysparkNote006---pycharm加载spark环境

pycharm配置pyspark环境&#xff0c;本地执行pyspark代码 spark安装、添加环境变量不提了 File-Settings-Project-Project Structure-add content root添加如下两个路径 D:\code\spark\python\lib\py4j-0.10.7-src.zipD:\code\spark\python\lib\pyspark.zip 2023-07-26 阴 于…

linux(进程)[6]

管理概念 先描述&#xff0c;再组织 进程 启动一个软件就相当于启动了一个进程 Linux下执行一条命令就在系统层面创建了一个进程&#xff01;&#xff01; 如何管理 进程对应的代码和数据 进程对应的PCB结构体 PCB&#xff08;process control block&#xff09; 在Linu…

Banana Pi BPI-KVM – 基于 Rockchip RK3568 SoC 的 KVM over IP 解决方案

Banana Pi 已经开始开发基于 Rockchip RK3568 SoC 的 BPI-KVM 盒&#xff0c;但它不是迷你 PC&#xff0c;而是 KVM over IP 解决方案&#xff0c;旨在远程控制另一台计算机或设备&#xff0c;就像您在现场一样&#xff0c;例如能够打开和关闭连接的设备、访问 BIOS 等。 商业…

数据结构之顺序表

一、概念及结构 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构&#xff0c;一般情况下采用数组存 储。在数组上完成数据的增删查改。 顺序表一般可以分为&#xff1a; 1. 静态顺序表&#xff1a;使用定长数组存储元素。 2. 动态顺序表&#xff1a;使用动…

【SEO基础】百度权重是什么意思及网站关键词应该怎么选?

百度权重是什么意思及网站关键词应该怎么选&#xff1f; 正文共&#xff1a;3253字 20图 预计阅读时间&#xff1a;9分钟 ​ 1.什么是网站权重&#xff1f; 这段时间和一些朋友聊到网站权重以及关键词&#xff0c;发现蛮多人对于这两个概念的认知还是存在一些错误的&#xf…