SpringBoot2.5.6整合Elasticsearch7.12.1

news2024/11/18 22:50:35

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}]

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c++里的基础类 is_empty_v<_Ty1>

&#xff08;1&#xff09;为什么要研究这个问题&#xff0c;因为包括智能指针等很多源代码里都会使用 _Compressed_pair 这个类&#xff0c;其是一对值。研究这个类&#xff0c;就牵涉另一个更基础的类 is_empty_v<_Ty1> &#xff08;2&#xff09; is_empty_v<_Ty1&…

内部类(下)匿名内部类,静态内部类的使用

文章目录 前言一、匿名内部类二、静态内部类三、内部类的继承总结 前言 该文将会介绍匿名内部类、静态内部类的使用&#xff0c;补充完毕java中的内部类。补充内容为向上转型为接口、使用this关键字获取引用、内部类的继承。 一、匿名内部类 定义&#xff1a;没有名称的内部类。…

redis 淘汰策略和持久化

文章目录 一、淘汰策略1.1 背景1.2 淘汰策略 二、持久化2.1 AOF日志2.1.1 AOF配置2.1.2 AOF策略2.1.3 AOF缺点2.1.4 AOF Rewrite2.1.5 AOF Rewrite配置2.1.6 AOF Rewrite缺点2.1.7 fork进程时的写时复制2.1.8 大key对持久化的影响 2.2 RDB快照2.2.1 RDB配置2.2.2 RDB缺点 2.3 混…

二分查找算法(全网最详细代码演示)

二分查找也称 半查找&#xff08;Binary Search&#xff09;&#xff0c;它时一种效率较高的查找方法。但是&#xff0c;折半查找要求线性表必须采用顺序存储结构&#xff0c;而且表中元素按关键字 有序 排列。 注意&#xff1a;使用二分查找的前提是 该数组是有序的。 在实际开…

web前端常用调试工具

概述 当我们写 webapp 或者 移动端H5网页时&#xff0c;要在手机上调试并不容易。 alert&#xff1a;很早之前的调试办法&#xff08;已被抛弃&#xff09; vconsole&#xff1a;是2016年由微信公众平台前端团队推出&#xff08;目前大量使用&#xff09; eruda&#xff1a…

解读随机森林的决策树:揭示模型背后的奥秘

一、引言 随机森林[1]是一种强大的机器学习算法&#xff0c;在许多领域都取得了显著的成功。它由多个决策树组成&#xff0c;而决策树则是构建随机森林的基本组件之一。通过深入解析决策树&#xff0c;我们可以更好地理解随机森林模型的工作原理和内在机制。 决策树是一种树状结…

虚拟现实技术(VR)

目录 1.什么是虚拟现实技术 2.虚拟现实技术的由来 3.虚拟现实技术给人类带来的好处 4.虚拟现实技术未来的走向 1.什么是虚拟现实技术 虚拟现实技术&#xff08;Virtual Reality&#xff0c;简称VR&#xff09;是一种通过计算机生成的模拟环境&#xff0c;使用户能够身临其境…

【js】经纬度位置获取navigator.geolocation.getCurrentPosition:

文章目录 一、经纬度位置获取navigator.geolocation.getCurrentPosition二、getCurrentPosition()在google chrome上不起作用 一、经纬度位置获取navigator.geolocation.getCurrentPosition 【文档】https://developer.mozilla.org/zh-CN/docs/Web/API/Window/navigator // 获取…

Redis 数据库高可用

Redis 数据库的高可用 一.Redis 数据库的持久化 1.Redis 高可用概念 &#xff08;1&#xff09;在web服务器中&#xff0c;高可用是指服务器可以正常访问的时间&#xff0c;衡量的标准是在多长时间内可以提供正常服务&#xff08;99.9%、99.99%、99.999%等等&#xff09;。 …

《MySQL 实战 45 讲》课程学习笔记(三)

事务隔离 事务就是要保证一组数据库操作&#xff0c;要么全部成功&#xff0c;要么全部失败。 隔离性与隔离级别 事务特性&#xff1a;ACID&#xff08;Atomicity、Consistency、Isolation、Durability&#xff0c;即原子性、一致性、隔离性、持久性&#xff09;。当数据库上…

Web-1-网站工作流程介绍

我们学习web开发&#xff0c;首先要知道什么是Web&#xff1f; Web: 全球广域网&#xff0c;也称为万维网(www World Wide Web)&#xff0c;能够通过浏览器访问的网站 比如我展示的这京东&#xff0c;淘宝唯品会都叫做网站&#xff0c;那么现在大家想一下&#xff0c;你还知道什…

用Ubuntu交叉编译Linux内核源码并部署到树莓派4B上

参考文章 1. 配置交叉编译环境 之前在ubuntu上配置过了&#xff0c;直接跳过 2.获取Linux内核源码 Linux内核源码链接 到链接里面选择自己合适版本的内核源码下载下来&#xff0c;然后传到ubuntu中进行解压 3.Linux内核源码的配置 参考文章 厂家配linux内核源码&#xff…

数据可视化库pyecharts简单入门

文章目录 0. 介绍1. 快速开始1.1 安装1.1.1 pip安装1.1.2 源码安装 1.2 快速上手1.2.1 柱状图1.2.2 链式调用1.2.3 使用options选项配置参数&#xff08;一切皆options&#xff09;1.2.4 渲染成图片文件1.2.5 使用主题1.2.6 地图 2. 全局配置项2.1 使用指南2.2 常用全局配置项2…

直呼牛逼!阿里最新 SpringBoot 进阶笔记涵盖了 SpringBoot 所有骚操作

相信从事 Java 开发的朋友都听说过 SSM 框架&#xff0c;老点的甚至经历过 SSH&#xff0c;说起来有点恐怖&#xff0c;比如我就是经历过 SSH 那个时代未流。当然无论是 SSM 还是 SSH 都不是今天的重点&#xff0c;今天要说的是 Spring Boot&#xff0c;一个令人眼前一亮的框架…

Intellij IDEA有什么奇技淫巧?

IDEA全称 IntelliJIDEA&#xff0c;是java语言开发的集成环境&#xff0c;IntelliJ在业界被公认为最好的java开发工具之一&#xff0c;尤其在智能代码助手、代码自动提示、重构、J2EE支持、Ant、JUnit、CVS整合、代码审查、创新的GUI设计等方面的功能可以说是超常的。 idea下载…

【大数据趋势】7月30日 汇率,恒指期货的大数据趋势概率分析。

1. 数据源头之一 : 汇率变化 从程序模拟趋势来看&#xff0c;美元在持续弱势状态&#xff0c;周线上正在构建一个新的下跌趋势&#xff0c;而且正在反抽过程中&#xff0c;即将完成&#xff0c;如果没有外部干预&#xff0c;会顺势往下。从月线来看&#xff0c;高点逐步降低&a…

【论文笔记】神经网络压缩调研

神经网络压缩调研 背景现有的深度模型压缩方法NetWork Prunning 网络剪枝设计结构化矩阵知识蒸馏权值共享Parameter Quantization&#xff08;参数量化&#xff09;量化和二进制化伪量化Architecture Design&#xff08;Depth Separable Convolution&#xff09;分解卷积 背景 …

【Linux】进程轻松入门

目录 一&#xff0c; 冯* 诺依曼体系结构 1&#xff0c;存储结构 ​编辑 二&#xff0c; 操作系统 1&#xff0c;概念 2&#xff0c;设计OS的目的 3&#xff0c;定位 4&#xff0c;如何理解 "管理" 5&#xff0c; 总结 三&#xff0c;进程 1. 概念 那么…

【C语言所有操作符详解2】

目录 条件操作符 逗号表达式 下标引用、函数调用和结构成员 [ ] 下标引用操作符 ( ) 函数调用操作符 访问一个结构的成员 表达式求值 隐式类型转换 隐式类型转换 整型提升 整型提升的意义: 如何进行整型提升呢? 算术转换 操作符的属性 操作符优先级 …

Redis系列一:介绍

介绍 The open source, in-memory data store used by millions of developers as a database, cache, streaming engine, and message broker. 相关资源 Redis 官网&#xff1a;https://redis.io/ 源码地址&#xff1a;https://github.com/redis/redis Redis 在线测试&#…