lyhzzz 2 anni fa
parent
commit
8572aa718a

+ 12 - 4
4dkankan-common-utils/src/main/java/com/fdkankan/common/constant/ImageUtil.java

@@ -1,5 +1,10 @@
 package com.fdkankan.common.constant;
 
+import cn.hutool.core.img.ImgUtil;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -78,10 +83,13 @@ public class ImageUtil {
         return stringBuilder.toString();
     }
 
-    public static void main(String[] args) throws Exception{
-        FileInputStream fis = new FileInputStream(new File("F:\\test\\1.png"));
-        boolean image = ImageUtil.isImage(fis);
-        System.out.println(image);
+    public static void main(String[] args) throws IOException {
+        ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
+        String path = "G:\\home\\backend\\4dkankan_v4\\sale\\file\\sale\\file\\test\\5474a1e8d93747f3aec79e6021c10a3b.png";
+        String picType = getPicType(new FileInputStream(path));
+        System.out.println(picType);
+        BufferedImage read = ImgUtil.read(new File(path));
+        ImageIO.write(read, "png", byteArrayOut);
     }
 
 }

+ 64 - 0
4dkankan-utils-elasticsearch/pom.xml

@@ -0,0 +1,64 @@
+<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>4dkankan-utils</artifactId>
+        <groupId>com.fdkankan</groupId>
+        <version>3.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>4dkankan-utils-elasticsearch</artifactId>
+
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+
+        <!--引入es-high-level-client相关依赖  start-->
+        <dependency>
+            <groupId>org.elasticsearch</groupId>
+            <artifactId>elasticsearch</artifactId>
+            <version>6.8.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.elasticsearch.client</groupId>
+            <artifactId>elasticsearch-rest-client</artifactId>
+            <version>6.8.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.elasticsearch.client</groupId>
+            <artifactId>elasticsearch-rest-high-level-client</artifactId>
+            <version>6.8.2</version>
+        </dependency>
+        <!--引入es-high-level-client相关依赖  end-->
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.83</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-collections</groupId>
+            <artifactId>commons-collections</artifactId>
+            <version>3.2.2</version>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 115 - 0
4dkankan-utils-elasticsearch/src/main/java/com/fdkankan/elasticsearch/config/ElasticsearchConfig.java

@@ -0,0 +1,115 @@
+package com.fdkankan.elasticsearch.config;
+
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.elasticsearch.client.RestClient;
+import org.elasticsearch.client.RestClientBuilder;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author yanfengzhang
+ * @description restHighLevelClient 客户端配置类
+ * @date 2022/12/7  23:34
+ */
+
+@Slf4j
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "elasticsearch")
+public class ElasticsearchConfig {
+    /**
+     * es host ip 地址(集群)
+     */
+    private String hosts;
+    /**
+     * es用户名
+     */
+    private String userName;
+    /**
+     * es密码
+     */
+    private String password;
+    /**
+     * es 请求方式
+     */
+    private String scheme;
+    /**
+     * es集群名称
+     */
+    private String clusterName;
+    /**
+     * es 连接超时时间
+     */
+    private int connectTimeOut;
+    /**
+     * es socket 连接超时时间
+     */
+    private int socketTimeOut;
+    /**
+     * es 请求超时时间
+     */
+    private int connectionRequestTimeOut;
+    /**
+     * es 最大连接数
+     */
+    private int maxConnectNum;
+    /**
+     * es 每个路由的最大连接数
+     */
+    private int maxConnectNumPerRoute;
+
+    /**
+     * 如果@Bean没有指定bean的名称,那么这个bean的名称就是方法名
+     */
+    @Bean(name = "restHighLevelClient")
+    public RestHighLevelClient restHighLevelClient() {
+        /** 拆分地址
+         /**        List<HttpHost> hostLists = new ArrayList<>();
+         /**        String[] hostList = hosts.split(",");
+         /**        for (String addr : hostList) {
+         /**            String host = addr.split(":")[0];
+         /**            String port = addr.split(":")[1];
+         /**            hostLists.add(new HttpHost(host, Integer.parseInt(port), scheme));
+         /**        }
+         /**        /** 转换成 HttpHost 数组
+         /**        HttpHost[] httpHost = hostLists.toArray(new HttpHost[]{});*/
+
+        /*此处为单节点es*/
+        String host = hosts.split(":")[0];
+        String port = hosts.split(":")[1];
+        HttpHost httpHost = new HttpHost(host, Integer.parseInt(port));
+
+        /*构建连接对象*/
+        RestClientBuilder builder = RestClient.builder(httpHost);
+
+        /*设置用户名、密码*/
+        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
+        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(userName, password));
+
+        /*连接延时配置*/
+        builder.setRequestConfigCallback(requestConfigBuilder -> {
+            requestConfigBuilder.setConnectTimeout(connectTimeOut);
+            requestConfigBuilder.setSocketTimeout(socketTimeOut);
+            requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeOut);
+            return requestConfigBuilder;
+        });
+
+        /*连接数配置*/
+        builder.setHttpClientConfigCallback(httpClientBuilder -> {
+            httpClientBuilder.setMaxConnTotal(maxConnectNum);
+            httpClientBuilder.setMaxConnPerRoute(maxConnectNumPerRoute);
+            httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
+            return httpClientBuilder;
+        });
+
+        return new RestHighLevelClient(builder);
+    }
+}

+ 64 - 0
4dkankan-utils-elasticsearch/src/main/java/com/fdkankan/elasticsearch/service/DocumentService.java

@@ -0,0 +1,64 @@
+package com.fdkankan.elasticsearch.service;
+
+import com.alibaba.fastjson.JSONObject;
+import org.elasticsearch.rest.RestStatus;
+
+import java.io.IOException;
+import java.util.List;
+
+public interface  DocumentService {
+
+    /**
+     * 增加文档信息
+     *
+     * @param indexName 索引名
+     * @param type      文档类型
+     * @param keyId     主键
+     * @param data      json数据
+     * @return 增加文档信息状态
+     * @throws IOException 异常信息
+     */
+    RestStatus addDocument(String indexName, String type, String keyId,String data) throws IOException;
+
+    /**
+     * 获取文档信息
+     *
+     * @param indexName 索引名
+     * @param type      文档类型
+     * @param id        文档ID
+     * @return 商品数据
+     * @throws Exception 异常信息
+     */
+    String getDocument(String indexName, String type, String id) throws Exception;
+
+    /**
+     * 更新文档信息
+     *
+     * @param indexName 索引名
+     * @param type      文档类型
+     * @param data      数据
+     * @return 更新文档信息状态
+     * @throws IOException 异常信息
+     */
+    RestStatus updateDocument(String indexName, String type, String id ,String data) throws IOException;
+
+    /**
+     * 删除文档信息
+     *
+     * @param indexName 索引名
+     * @param type      文档类型
+     * @param id        文档ID
+     * @return 删除文档信息状态
+     * @throws IOException 异常信息
+     */
+    RestStatus deleteDocument(String indexName, String type, String id) throws IOException;
+
+    /**
+     * 批量导入
+     *
+     * @param dataList 商品列表
+     * @return 批量导入状态
+     * @throws IOException 异常信息
+     */
+    RestStatus batchImportGoodsData(List<JSONObject> dataList, String index) throws IOException;
+}

+ 45 - 0
4dkankan-utils-elasticsearch/src/main/java/com/fdkankan/elasticsearch/service/IndexService.java

@@ -0,0 +1,45 @@
+package com.fdkankan.elasticsearch.service;
+
+
+import java.util.Map;
+
+public interface IndexService {
+
+
+    /**
+     * 创建索引
+     *
+     * @param indexName 索引名
+     * @param mapping   映射结构配置
+     * @return true-创建成功
+     * @throws Exception 异常
+     */
+    boolean indexCreate(String indexName, String mapping) throws Exception;
+
+    /**
+     * 获取索引结构
+     *
+     * @param indexName 索引名
+     * @return 索引结构
+     * @throws Exception 异常
+     */
+    Map<String, Object> getMapping(String indexName) throws Exception;
+
+    /**
+     * 删除索引库
+     *
+     * @param indexName 索引名
+     * @return true-删除成功
+     * @throws Exception 异常
+     */
+    boolean indexDelete(String indexName) throws Exception;
+
+    /**
+     * 判断索引是否存在
+     *
+     * @param indexName 索引名
+     * @return true-存在
+     * @throws Exception 异常
+     */
+    boolean indexExists(String indexName) throws Exception;
+}

+ 149 - 0
4dkankan-utils-elasticsearch/src/main/java/com/fdkankan/elasticsearch/service/QueryDataService.java

@@ -0,0 +1,149 @@
+package com.fdkankan.elasticsearch.service;
+
+import java.util.List;
+
+public interface QueryDataService {
+
+    /**
+     * 精确查询(termQuery)
+     *
+     * @param indexName  索引名
+     * @param columnName 列名或字段名
+     * @param value      查询内容
+     * @param classz     数据结构
+     * @param <T>        数据结构
+     * @return 精确查询内容数据
+     */
+    <T> List<T> termQuery(String indexName, String columnName, Object value, Class<T> classz);
+
+    /**
+     * terms:多个查询内容在一个字段中进行查询
+     *
+     * @param indexName  索引名
+     * @param columnName 列名或字段名
+     * @param dataArgs   查询内容集合
+     * @param classz     数据结构
+     * @param <T>        数据结构
+     * @return 多个查询内容在一个字段中进行查询对应结果
+     */
+    <T> List<T> termsQuery(String indexName, String columnName, Object[] dataArgs, Class<T> classz);
+
+    /**
+     * 匹配查询符合条件的所有数据,并设置分页
+     *
+     * @param indexName  索引名
+     * @param classz     数据结构
+     * @param startIndex 起始下标
+     * @param pageSize   页大小
+     * @param orderList  设置排序
+     * @param columnName 列名或字段名
+     * @param value      列名或字段名指定内容
+     * @param <T>        数据结构
+     * @return 符合条件的所有数据
+     */
+    <T> List<T> matchAllQuery(String indexName, Class<T> classz, int startIndex, int pageSize, List<String> orderList, String columnName, Object value);
+
+    /**
+     * 词语匹配查询
+     *
+     * @param indexName  索引名
+     * @param classz     数据结构
+     * @param columnName 列名或字段名
+     * @param value      指定内容
+     * @param <T>        数据结构
+     * @return 词语匹配查询结果
+     */
+    <T> List<T> matchPhraseQuery(String indexName, Class<T> classz, String columnName, Object value);
+
+    /**
+     * 内容在多字段中进行查询
+     *
+     * @param indexName 索引名
+     * @param classz    数据结构
+     * @param fields    列名或字段名集合
+     * @param text      指定内容
+     * @param <T>       数据结构
+     * @return 查询结果
+     */
+    <T> List<T> matchMultiQuery(String indexName, Class<T> classz, String[] fields, Object text);
+
+    /**
+     * 通配符查询(wildcard):会对查询条件进行分词。还可以使用通配符 ?(任意单个字符) 和 * (0个或多个字符)
+     *
+     * @param indexName 索引名
+     * @param classz    数据结构
+     * @param field     列名或字段名集合
+     * @param text      指定内容
+     * @param <T>       数据结构
+     * @return 查询结果
+     */
+    <T> List<T> wildcardQuery(String indexName, Class<T> classz, String field, String text);
+
+    /**
+     * 模糊查询商品信息
+     *
+     * @param indexName 索引名
+     * @param classz    数据结构
+     * @param field     列名或字段名集合
+     * @param text      指定内容
+     * @param <T>       数据结构
+     * @return 查询结果
+     */
+    <T> List<T> fuzzyQuery(String indexName, Class<T> classz, String field, String text);
+
+    /**
+     * boolQuery 查询
+     * 高亮展示标题搜索字段
+     * 设置出参返回字段
+     * 案例:查询从2018-2022年间标题含 三星 的商品信息
+     *
+     * @param indexName 索引名
+     * @param beanClass 数据结构
+     * @param <T>       数据结构
+     * @return 查询结果
+     */
+    <T> List<T> boolQuery(String indexName, Class<T> beanClass);
+
+    /**
+     * 聚合查询 : 聚合查询一定是【先查出结果】,然后对【结果使用聚合函数】做处理.
+     * Metric 指标聚合分析。常用的操作有:avg:求平均、max:最大值、min:最小值、sum:求和等
+     * 案例:分别获取最贵的商品和获取最便宜的商品
+     *
+     * @param indexName 索引名
+     */
+    void metricQuery(String indexName);
+
+    /**
+     * 聚合查询: 聚合查询一定是【先查出结果】,然后对【结果使用聚合函数】做处理
+     * Bucket 分桶聚合分析 : 对查询出的数据进行分组group by,再在组上进行游标聚合
+     * 案例:根据品牌进行聚合查询
+     *
+     * @param indexName        索引名
+     * @param bucketField
+     * @param bucketFieldAlias
+     */
+    void bucketQuery(String indexName, String bucketField, String bucketFieldAlias);
+
+    /**
+     * 子聚合聚合查询  Bucket 分桶聚合分析
+     * <p>
+     * 案例:根据商品分类进行分组查询,并且获取分类商品中的平均价格
+     *
+     * @param indexName        索引名
+     * @param bucketField
+     * @param bucketFieldAlias
+     * @param avgFiled
+     * @param avgFiledAlias
+     */
+    void subBucketQuery(String indexName, String bucketField, String bucketFieldAlias, String avgFiled, String avgFiledAlias);
+
+    /**
+     * 综合聚合查询
+     * <p>
+     * 根据商品分类聚合,获取每个商品类的平均价格,并且在商品分类聚合之上子聚合每个品牌的平均价格
+     *
+     * @param indexName 索引名
+     */
+    void subSubAgg(String indexName);
+
+}

+ 161 - 0
4dkankan-utils-elasticsearch/src/main/java/com/fdkankan/elasticsearch/service/impl/DocumentServiceImpl.java

@@ -0,0 +1,161 @@
+package com.fdkankan.elasticsearch.service.impl;
+
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.elasticsearch.service.DocumentService;
+import lombok.extern.log4j.Log4j2;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+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.get.GetRequest;
+import org.elasticsearch.action.get.GetResponse;
+import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.action.index.IndexResponse;
+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.common.xcontent.XContentType;
+import org.elasticsearch.rest.RestStatus;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.util.List;
+
+@Slf4j
+@Service
+public class DocumentServiceImpl implements DocumentService {
+
+    @Autowired
+    private RestHighLevelClient restHighLevelClient;
+
+    /**
+     * 增加文档信息
+     *
+     * @param indexName 索引名
+     * @param type      文档类型
+     * @param keyId     主键
+     * @param data      json数据
+     * @return 增加文档信息状态
+     * @throws IOException 异常信息
+     */
+    @Override
+    public RestStatus addDocument(String indexName, String type,String keyId, String data) throws IOException {
+        /*1.默认类型为_doc*/
+        if (StringUtils.isBlank(type)) {
+            type = "_doc";
+        }
+        /*2.将对象转为json*/
+        /*3.创建索引请求对象*/
+        IndexRequest indexRequest = new IndexRequest(indexName, type).id(keyId).source(data, XContentType.JSON);
+        /*4.执行增加文档*/
+        IndexResponse response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
+
+        return response.status();
+    }
+
+    /**
+     * 获取文档信息
+     *
+     * @param indexName 索引名
+     * @param type      文档类型
+     * @param id        文档ID
+     * @return 商品数据
+     * @throws Exception 异常信息
+     */
+    @Override
+    public String getDocument(String indexName, String type, String id) throws Exception {
+        /*1.默认类型为_doc*/
+        if (StringUtils.isBlank(type)) {
+            type = "_doc";
+        }
+        /*2.创建获取请求对象*/
+        GetRequest getRequest = new GetRequest(indexName, type, id);
+        GetResponse response = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
+
+        return response.getSourceAsString();
+    }
+
+    /**
+     * 更新文档信息
+     *
+     * @param indexName 索引名
+     * @param type      文档类型
+     * @param data      数据
+     * @return 更新文档信息状态
+     * @throws IOException 异常信息
+     */
+    @Override
+    public RestStatus updateDocument(String indexName, String type, String id ,String data) throws IOException {
+        /*1.默认类型为_doc*/
+        if (StringUtils.isBlank(type)) {
+            type = "_doc";
+        }
+
+        /*2.创建索引请求对象*/
+        UpdateRequest updateRequest = new UpdateRequest(indexName, type, id);
+        /*3.设置更新文档内容*/
+        updateRequest.doc(data, XContentType.JSON);
+        /*4.执行更新文档*/
+        UpdateResponse response = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
+
+        return response.status();
+    }
+
+    /**
+     * 删除文档信息
+     *
+     * @param indexName 索引名
+     * @param type      文档类型
+     * @param id        文档ID
+     * @return 删除文档信息状态
+     * @throws IOException 异常信息
+     */
+    @Override
+    public RestStatus deleteDocument(String indexName, String type, String id) throws IOException {
+        /*1.默认类型为_doc*/
+        if (StringUtils.isBlank(type)) {
+            type = "_doc";
+        }
+
+        /*2.创建删除请求对象*/
+        DeleteRequest deleteRequest = new DeleteRequest(indexName, type, id);
+        /*3.执行删除文档*/
+        DeleteResponse response = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
+
+        return response.status();
+    }
+
+    /**
+     * 批量导入
+     *
+     * @param dataList 列表
+     * @return 批量导入状态
+     * @throws IOException 异常信息
+     */
+    @Override
+    public RestStatus batchImportGoodsData(List<JSONObject> dataList, String index) throws IOException {
+        if (CollectionUtils.isEmpty(dataList)) {
+            return RestStatus.CREATED;
+        }
+
+        /*bulk导入 循环goodsList,创建IndexRequest添加数据*/
+        BulkRequest bulkRequest = new BulkRequest();
+        for (JSONObject data : dataList) {
+            //将goods对象转换为json字符串
+            IndexRequest indexRequest = new IndexRequest(index, "_doc");
+            indexRequest.id(data.getString("id")).source(data, XContentType.JSON);
+            bulkRequest.add(indexRequest);
+        }
+
+        BulkResponse response = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
+        return response.status();
+    }
+
+}

+ 106 - 0
4dkankan-utils-elasticsearch/src/main/java/com/fdkankan/elasticsearch/service/impl/IndexServiceImpl.java

@@ -0,0 +1,106 @@
+package com.fdkankan.elasticsearch.service.impl;
+
+
+import com.fdkankan.elasticsearch.service.IndexService;
+import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
+import org.elasticsearch.client.IndicesClient;
+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.GetIndexResponse;
+import org.elasticsearch.cluster.metadata.MappingMetaData;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+
+@Service
+public class IndexServiceImpl implements IndexService {
+
+    @Autowired
+    private RestHighLevelClient restHighLevelClient;
+
+
+
+    /**
+     * 创建索引
+     *
+     * @param indexName 索引名
+     * @param mapping   映射结构配置
+     * @return true-创建成功
+     * @throws Exception 异常
+     */
+    @Override
+    public boolean indexCreate(String indexName, String mapping) throws Exception {
+        CreateIndexRequest indexRequest = new CreateIndexRequest(indexName);
+
+        IndicesClient indicesClient = restHighLevelClient.indices();
+        indexRequest.mapping(mapping, XContentType.JSON);
+
+        // 请求服务器
+        CreateIndexResponse response = indicesClient.create(indexRequest, RequestOptions.DEFAULT);
+
+        return response.isAcknowledged();
+    }
+
+    /**
+     * 获取索引结构
+     *
+     * @param indexName 索引名
+     * @return 索引结构
+     * @throws Exception 异常
+     */
+    @Override
+    public Map<String, Object> getMapping(String indexName) throws Exception {
+        IndicesClient indicesClient = restHighLevelClient.indices();
+
+        // 创建get请求
+        GetIndexRequest request = new GetIndexRequest(indexName);
+        // 发送get请求
+        GetIndexResponse response = indicesClient.get(request, RequestOptions.DEFAULT);
+        // 获取表结构
+        Map<String, MappingMetaData> mappings = response.getMappings();
+        Map<String, Object> sourceAsMap = mappings.get(indexName).getSourceAsMap();
+        return sourceAsMap;
+    }
+
+    /**
+     * 删除索引库
+     *
+     * @param indexName 索引名
+     * @return true-删除成功
+     * @throws Exception 异常
+     */
+    @Override
+    public boolean indexDelete(String indexName) throws Exception {
+        IndicesClient indicesClient = restHighLevelClient.indices();
+        // 创建delete请求方式
+        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indexName);
+        // 发送delete请求
+        AcknowledgedResponse response = indicesClient.delete(deleteIndexRequest, RequestOptions.DEFAULT);
+
+        return response.isAcknowledged();
+    }
+
+    /**
+     * 判断索引是否存在
+     *
+     * @param indexName 索引名
+     * @return true-存在
+     * @throws Exception 异常
+     */
+    @Override
+    public boolean indexExists(String indexName) throws Exception {
+        IndicesClient indicesClient = restHighLevelClient.indices();
+        // 创建get请求
+        GetIndexRequest request = new GetIndexRequest(indexName);
+        // 判断索引库是否存在
+        return indicesClient.exists(request, RequestOptions.DEFAULT);
+    }
+
+}

+ 542 - 0
4dkankan-utils-elasticsearch/src/main/java/com/fdkankan/elasticsearch/service/impl/QueryDataServiceImpl.java

@@ -0,0 +1,542 @@
+package com.fdkankan.elasticsearch.service.impl;
+
+
+import com.alibaba.fastjson.JSON;
+import com.fdkankan.elasticsearch.service.QueryDataService;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.elasticsearch.action.search.SearchRequest;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.common.text.Text;
+import org.elasticsearch.common.unit.Fuzziness;
+import org.elasticsearch.index.query.BoolQueryBuilder;
+import org.elasticsearch.index.query.MatchAllQueryBuilder;
+import org.elasticsearch.index.query.MatchQueryBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.rest.RestStatus;
+import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.SearchHits;
+import org.elasticsearch.search.aggregations.AggregationBuilder;
+import org.elasticsearch.search.aggregations.AggregationBuilders;
+import org.elasticsearch.search.aggregations.Aggregations;
+import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
+import org.elasticsearch.search.aggregations.bucket.terms.Terms;
+import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
+import org.elasticsearch.search.aggregations.metrics.avg.ParsedAvg;
+import org.elasticsearch.search.aggregations.metrics.max.ParsedMax;
+import org.elasticsearch.search.aggregations.metrics.min.ParsedMin;
+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.SortOrder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * @author yanfengzhang
+ * @description
+ * @date 2022/12/8  23:37
+ */
+@Service
+@Log4j2
+public class QueryDataServiceImpl implements QueryDataService {
+    @Autowired
+    private RestHighLevelClient restHighLevelClient;
+
+    /**
+     * 精确查询(termQuery)
+     *
+     * @param indexName  索引名
+     * @param columnName 列名或字段名
+     * @param value      查询内容
+     * @param classz     数据结构
+     * @param <T>        数据结构
+     * @return 精确查询内容数据
+     */
+    @Override
+    public <T> List<T> termQuery(String indexName, String columnName, Object value, Class<T> classz) {
+        /* 查询的数据列表 */
+        List<T> list = new ArrayList<>();
+        try {
+            /*构建查询条件(注意:termQuery 支持多种格式查询,如 boolean、int、double、string 等,这里使用的是 string 的查询)*/
+            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+            searchSourceBuilder.query(QueryBuilders.termQuery(columnName, value));
+            /*执行查询es数据*/
+            queryEsData(indexName, classz, list, searchSourceBuilder);
+        } catch (IOException e) {
+            log.error("精确查询数据失败,错误信息:", e);
+        }
+        return list;
+    }
+
+    /**
+     * terms:多个查询内容在一个字段中进行查询
+     *
+     * @param indexName  索引名
+     * @param columnName 列名或字段名
+     * @param dataArgs   查询内容集合
+     * @param classz     数据结构
+     * @param <T>        数据结构
+     * @return 多个查询内容在一个字段中进行查询对应结果
+     */
+    @Override
+    public <T> List<T> termsQuery(String indexName, String columnName, Object[] dataArgs, Class<T> classz) {
+        /*查询的数据列表*/
+        List<T> list = new ArrayList<>();
+        try {
+            /* 构建查询条件(注意:termsQuery 支持多种格式查询,如 boolean、int、double、string 等,这里使用的是 string 的查询)*/
+            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+            searchSourceBuilder.query(QueryBuilders.termsQuery(columnName, dataArgs));
+            /*展示100条,默认只展示10条记录*/
+            searchSourceBuilder.size(100);
+            /*执行查询es数据*/
+            queryEsData(indexName, classz, list, searchSourceBuilder);
+        } catch (IOException e) {
+            log.error("单字段多内容查询数据失败,错误信息:", e);
+        }
+        return list;
+    }
+
+    /**
+     * 匹配查询符合条件的所有数据,并设置分页
+     *
+     * @param indexName  索引名
+     * @param classz     数据结构
+     * @param startIndex 起始下标
+     * @param pageSize   页大小
+     * @param orderList  设置排序
+     * @param columnName 列名或字段名
+     * @param value      列名或字段名指定内容
+     * @param <T>        数据结构
+     * @return 符合条件的所有数据
+     */
+    @Override
+    public <T> List<T> matchAllQuery(String indexName, Class<T> classz, int startIndex, int pageSize, List<String> orderList, String columnName, Object value) {
+        /*查询的数据列表*/
+        List<T> list = new ArrayList<>();
+        try {
+            /*创建查询源构造器*/
+            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+
+            /*构建查询条件*/
+            if (StringUtils.isNotBlank(columnName) && Objects.nonNull(value)) {
+                MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(columnName, value);
+                searchSourceBuilder.query(matchQueryBuilder);
+            } else {
+                MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
+                searchSourceBuilder.query(matchAllQueryBuilder);
+            }
+
+            /*设置分页*/
+            searchSourceBuilder.from(startIndex);
+            searchSourceBuilder.size(pageSize);
+
+            /*设置排序*/
+            if (orderList != null) {
+                for (String order : orderList) {
+                    /*开头代表:倒序*/
+                    boolean flag = order.startsWith("-");
+                    SortOrder sort = flag ? SortOrder.DESC : SortOrder.ASC;
+                    order = flag ? order.substring(1) : order;
+                    searchSourceBuilder.sort(order, sort);
+                }
+            }
+            /*执行查询es数据*/
+            queryEsData(indexName, classz, list, searchSourceBuilder);
+        } catch (IOException e) {
+            log.error("查询所有数据失败,错误信息:", e);
+        }
+        return list;
+    }
+
+    /**
+     * 词语匹配查询
+     *
+     * @param indexName  索引名
+     * @param classz     数据结构
+     * @param columnName 列名或字段名
+     * @param value      指定内容
+     * @param <T>        数据结构
+     * @return 词语匹配查询结果
+     */
+    @Override
+    public <T> List<T> matchPhraseQuery(String indexName, Class<T> classz, String columnName, Object value) {
+        /*查询的数据列表*/
+        List<T> list = new ArrayList<>();
+        try {
+            /*构建查询条件*/
+            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+            searchSourceBuilder.query(QueryBuilders.matchPhraseQuery(columnName, value));
+            /*执行查询es数据*/
+            queryEsData(indexName, classz, list, searchSourceBuilder);
+        } catch (IOException e) {
+            log.error("词语匹配查询失败,错误信息:", e);
+        }
+        return list;
+    }
+
+    /**
+     * 内容在多字段中进行查询
+     *
+     * @param indexName 索引名
+     * @param classz    数据结构
+     * @param fields    列名或字段名集合
+     * @param text      指定内容
+     * @param <T>       数据结构
+     * @return 查询结果
+     */
+    @Override
+    public <T> List<T> matchMultiQuery(String indexName, Class<T> classz, String[] fields, Object text) {
+        /*查询的数据列表*/
+        List<T> list = new ArrayList<>();
+        try {
+            /*构建查询条件*/
+            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+            /*设置查询条件*/
+            searchSourceBuilder.query(QueryBuilders.multiMatchQuery(text, fields));
+            /*执行查询es数据*/
+            queryEsData(indexName, classz, list, searchSourceBuilder);
+        } catch (IOException e) {
+            log.error("词语匹配查询失败,错误信息:", e);
+        }
+        return list;
+    }
+
+    /**
+     * 通配符查询(wildcard):会对查询条件进行分词。还可以使用通配符 ?(任意单个字符) 和 * (0个或多个字符)
+     *
+     * @param indexName 索引名
+     * @param classz    数据结构
+     * @param field     列名或字段名集合
+     * @param text      指定内容
+     * @param <T>       数据结构
+     * @return 查询结果
+     */
+    @Override
+    public <T> List<T> wildcardQuery(String indexName, Class<T> classz, String field, String text) {
+        /*查询的数据列表*/
+        List<T> list = new ArrayList<>();
+        try {
+            /*构建查询条件*/
+            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+            searchSourceBuilder.query(QueryBuilders.wildcardQuery(field, text));
+            /*执行查询es数据*/
+            queryEsData(indexName, classz, list, searchSourceBuilder);
+        } catch (IOException e) {
+            log.error("通配符查询失败,错误信息:", e);
+        }
+        return list;
+    }
+
+    /**
+     * 模糊查询商品信息
+     *
+     * @param indexName 索引名
+     * @param classz    数据结构
+     * @param field     列名或字段名集合
+     * @param text      指定内容
+     * @param <T>       数据结构
+     * @return 查询结果
+     */
+    @Override
+    public <T> List<T> fuzzyQuery(String indexName, Class<T> classz, String field, String text) {
+        /*查询的数据列表*/
+        List<T> list = new ArrayList<>();
+        try {
+            /*构建查询条件*/
+            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+            searchSourceBuilder.query(QueryBuilders.fuzzyQuery(field, text).fuzziness(Fuzziness.AUTO));
+            /*执行查询es数据*/
+            queryEsData(indexName, classz, list, searchSourceBuilder);
+        } catch (IOException e) {
+            log.error("通配符查询失败,错误信息:", e);
+        }
+        return list;
+    }
+
+    /**
+     * boolQuery 查询
+     * 高亮展示标题搜索字段
+     * 设置出参返回字段
+     * 案例:查询从2018-2022年间标题含 三星 的商品信息
+     *
+     * @param indexName 索引名
+     * @param beanClass 数据结构
+     * @param <T>       数据结构
+     * @return 查询结果
+     */
+    @Override
+    public <T> List<T> boolQuery(String indexName, Class<T> beanClass) {
+        /*查询的数据列表*/
+        List<T> list = new ArrayList<>();
+        try {
+            /*创建 Bool 查询构建器*/
+            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
+            /*构建查询条件*/
+            boolQueryBuilder.must(QueryBuilders.matchQuery("title", "三星"));
+            boolQueryBuilder.must(QueryBuilders.matchQuery("spec", "联通3G"));
+            boolQueryBuilder.filter().add(QueryBuilders.rangeQuery("createTime").format("yyyy").gte("2018").lte("2022"));
+            /*构建查询源构建器*/
+            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+            searchSourceBuilder.query(boolQueryBuilder);
+            searchSourceBuilder.size(100);
+            /*甚至返回字段
+            如果查询的属性很少,那就使用includes,而excludes设置为空数组
+            如果排序的属性很少,那就使用excludes,而includes设置为空数组*/
+            String[] includes = {"title", "categoryName", "price"};
+            String[] excludes = {};
+            searchSourceBuilder.fetchSource(includes, excludes);
+            /*高亮设置
+            设置高亮三要素:  field: 你的高亮字段 , preTags :前缀    , postTags:后缀*/
+            HighlightBuilder highlightBuilder = new HighlightBuilder().field("title").preTags("<font color='red'>").postTags("</font>");
+            highlightBuilder.field("spec").preTags("<font color='red'>").postTags("</font>");
+            searchSourceBuilder.highlighter(highlightBuilder);
+            /*创建查询请求对象,将查询对象配置到其中*/
+            SearchRequest searchRequest = new SearchRequest(indexName);
+            searchRequest.source(searchSourceBuilder);
+            /*执行查询,然后处理响应结果*/
+            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
+            /*根据状态和数据条数验证是否返回了数据*/
+            if (RestStatus.OK.equals(searchResponse.status()) && searchResponse.getHits().getTotalHits() > 0) {
+                SearchHits hits = searchResponse.getHits();
+                for (SearchHit hit : hits) {
+                    /* 将 JSON 转换成对象*/
+                    T bean = JSON.parseObject(hit.getSourceAsString(), beanClass);
+                    /*获取高亮的数据*/
+                    HighlightField highlightField = hit.getHighlightFields().get("title");
+                    log.info("高亮名称:{}", highlightField.getFragments()[0].string());
+                    /*替换掉原来的数据*/
+                    Text[] fragments = highlightField.getFragments();
+                    if (fragments != null && fragments.length > 0) {
+                        StringBuilder title = new StringBuilder();
+                        for (Text fragment : fragments) {
+                            title.append(fragment);
+                        }
+                        /* 获取method对象,其中包含方法名称和参数列表*/
+                        Method setTitle = beanClass.getMethod("setTitle", String.class);
+                        if (setTitle != null) {
+                            /*执行method,bean为实例对象,后面是方法参数列表;setTitle没有返回值*/
+                            setTitle.invoke(bean, title.toString());
+                        }
+                    }
+                    list.add(bean);
+                }
+            }
+        } catch (Exception e) {
+            log.error("布尔查询失败,错误信息:", e);
+        }
+        return list;
+    }
+
+    /**
+     * 聚合查询 : 聚合查询一定是【先查出结果】,然后对【结果使用聚合函数】做处理.
+     * Metric 指标聚合分析。常用的操作有:avg:求平均、max:最大值、min:最小值、sum:求和等
+     * 案例:分别获取最贵的商品和获取最便宜的商品
+     *
+     * @param indexName 索引名
+     */
+    @Override
+    public void metricQuery(String indexName) {
+        try {
+            /* 构建查询条件*/
+            MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
+            /*创建查询源构造器*/
+            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+            searchSourceBuilder.query(matchAllQueryBuilder);
+
+            /*获取最贵的商品*/
+            AggregationBuilder maxPrice = AggregationBuilders.max("maxPrice").field("price");
+            searchSourceBuilder.aggregation(maxPrice);
+            /*获取最便宜的商品*/
+            AggregationBuilder minPrice = AggregationBuilders.min("minPrice").field("price");
+            searchSourceBuilder.aggregation(minPrice);
+
+            /*创建查询请求对象,将查询对象配置到其中*/
+            SearchRequest searchRequest = new SearchRequest(indexName);
+            searchRequest.source(searchSourceBuilder);
+            /*执行查询,然后处理响应结果*/
+            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
+            Aggregations aggregations = searchResponse.getAggregations();
+            ParsedMax max = aggregations.get("maxPrice");
+            log.info("最贵的价格:" + max.getValue());
+            ParsedMin min = aggregations.get("minPrice");
+            log.info("最便宜的价格:" + min.getValue());
+        } catch (Exception e) {
+            log.error("指标聚合分析查询失败,错误信息:", e);
+        }
+    }
+
+    /**
+     * 聚合查询: 聚合查询一定是【先查出结果】,然后对【结果使用聚合函数】做处理
+     * Bucket 分桶聚合分析 : 对查询出的数据进行分组group by,再在组上进行游标聚合
+     * 案例:根据品牌进行聚合查询
+     *
+     * @param indexName        索引名
+     * @param bucketField
+     * @param bucketFieldAlias
+     */
+    @Override
+    public void bucketQuery(String indexName, String bucketField, String bucketFieldAlias) {
+        try {
+            /*构建查询条件*/
+            MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
+            /*创建查询源构造器*/
+            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+            searchSourceBuilder.query(matchAllQueryBuilder);
+
+            /*根据bucketField进行分组查询*/
+            TermsAggregationBuilder aggBrandName = AggregationBuilders.terms(bucketFieldAlias).field(bucketField);
+            searchSourceBuilder.aggregation(aggBrandName);
+
+            /*创建查询请求对象,将查询对象配置到其中*/
+            SearchRequest searchRequest = new SearchRequest(indexName);
+            searchRequest.source(searchSourceBuilder);
+            /*执行查询,然后处理响应结果*/
+            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
+            Aggregations aggregations = searchResponse.getAggregations();
+            /*分组结果数据*/
+            ParsedStringTerms aggBrandName1 = aggregations.get(bucketFieldAlias);
+            for (Terms.Bucket bucket : aggBrandName1.getBuckets()) {
+                log.info(bucket.getKeyAsString() + "====" + bucket.getDocCount());
+            }
+        } catch (IOException e) {
+            log.error("分桶聚合分析查询失败,错误信息:", e);
+        }
+    }
+
+    /**
+     * 子聚合聚合查询  Bucket 分桶聚合分析
+     * <p>
+     * 案例:根据商品分类进行分组查询,并且获取分类商品中的平均价格
+     *
+     * @param indexName        索引名
+     * @param bucketField
+     * @param bucketFieldAlias
+     * @param avgFiled
+     * @param avgFiledAlias
+     */
+    @Override
+    public void subBucketQuery(String indexName, String bucketField, String bucketFieldAlias, String avgFiled, String avgFiledAlias) {
+        try {
+            /*构建查询条件*/
+            MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
+            /*创建查询源构造器*/
+            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+            searchSourceBuilder.query(matchAllQueryBuilder);
+
+            /* 根据 bucketField进行分组查询,并且获取分类信息中 指定字段的平均值*/
+            TermsAggregationBuilder subAggregation = AggregationBuilders.terms(bucketFieldAlias).field(bucketField)
+                    .subAggregation(AggregationBuilders.avg(avgFiledAlias).field(avgFiled));
+            searchSourceBuilder.aggregation(subAggregation);
+
+            /* 创建查询请求对象,将查询对象配置到其中*/
+            SearchRequest searchRequest = new SearchRequest(indexName);
+            searchRequest.source(searchSourceBuilder);
+            /*执行查询,然后处理响应结果*/
+            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
+            Aggregations aggregations = searchResponse.getAggregations();
+            ParsedStringTerms aggBrandName1 = aggregations.get(bucketFieldAlias);
+            for (Terms.Bucket bucket : aggBrandName1.getBuckets()) {
+                /*获取聚合后的 组内字段平均值,注意返回值不是Aggregation对象,而是指定的ParsedAvg对象*/
+                ParsedAvg avgPrice = bucket.getAggregations().get(avgFiledAlias);
+                log.info(bucket.getKeyAsString() + "====" + avgPrice.getValueAsString());
+            }
+        } catch (IOException e) {
+            log.error("分桶聚合分析查询失败,错误信息:", e);
+        }
+    }
+
+    /**
+     * 综合聚合查询
+     * <p>
+     * 根据商品分类聚合,获取每个商品类的平均价格,并且在商品分类聚合之上子聚合每个品牌的平均价格
+     *
+     * @param indexName 索引名
+     */
+    @Override
+    public void subSubAgg(String indexName) {
+        try {
+            /*构建查询条件*/
+            MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
+            /*创建查询源构造器*/
+            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+            searchSourceBuilder.query(matchAllQueryBuilder);
+
+            /*注意这里聚合写的位置不要写错,很容易搞混,错一个括号就不对了*/
+            TermsAggregationBuilder subAggregation = AggregationBuilders.terms("categoryNameAgg").field("categoryName")
+                    .subAggregation(AggregationBuilders.avg("categoryNameAvgPrice").field("price"))
+                    .subAggregation(AggregationBuilders.terms("brandNameAgg").field("brandName")
+                            .subAggregation(AggregationBuilders.avg("brandNameAvgPrice").field("price")));
+            searchSourceBuilder.aggregation(subAggregation);
+
+            /*创建查询请求对象,将查询对象配置到其中*/
+            SearchRequest searchRequest = new SearchRequest(indexName);
+            searchRequest.source(searchSourceBuilder);
+            /*执行查询,然后处理响应结果*/
+            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
+            /*获取总记录数*/
+            log.info("totalHits = " + searchResponse.getHits().getTotalHits());
+            /*获取聚合信息*/
+            Aggregations aggregations = searchResponse.getAggregations();
+            ParsedStringTerms categoryNameAgg = aggregations.get("categoryNameAgg");
+
+            /*获取值返回*/
+            for (Terms.Bucket bucket : categoryNameAgg.getBuckets()) {
+                /*获取聚合后的分类名称*/
+                String categoryName = bucket.getKeyAsString();
+                /*获取聚合命中的文档数量*/
+                long docCount = bucket.getDocCount();
+                /*获取聚合后的分类的平均价格,注意返回值不是Aggregation对象,而是指定的ParsedAvg对象*/
+                ParsedAvg avgPrice = bucket.getAggregations().get("categoryNameAvgPrice");
+                log.info(categoryName + "======平均价:" + avgPrice.getValue() + "======数量:" + docCount);
+
+                ParsedStringTerms brandNameAgg = bucket.getAggregations().get("brandNameAgg");
+                for (Terms.Bucket brandeNameAggBucket : brandNameAgg.getBuckets()) {
+                    /*获取聚合后的品牌名称*/
+                    String brandName = brandeNameAggBucket.getKeyAsString();
+                    /*获取聚合后的品牌的平均价格,注意返回值不是Aggregation对象,而是指定的ParsedAvg对象*/
+                    ParsedAvg brandNameAvgPrice = brandeNameAggBucket.getAggregations().get("brandNameAvgPrice");
+                    log.info("     " + brandName + "======" + brandNameAvgPrice.getValue());
+                }
+            }
+        } catch (IOException e) {
+            log.error("综合聚合查询失败,错误信息:", e);
+        }
+    }
+
+
+    /**
+     * 执行es查询
+     *
+     * @param indexName
+     * @param beanClass
+     * @param list
+     * @param searchSourceBuilder
+     * @param <T>
+     * @throws IOException
+     */
+    private <T> void queryEsData(String indexName, Class<T> beanClass, List<T> list, SearchSourceBuilder searchSourceBuilder) throws IOException {
+        /*创建查询请求对象,将查询对象配置到其中*/
+        SearchRequest searchRequest = new SearchRequest(indexName);
+        searchRequest.source(searchSourceBuilder);
+        /*执行查询,然后处理响应结果*/
+        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
+        /*根据状态和数据条数验证是否返回了数据*/
+        if (RestStatus.OK.equals(searchResponse.status()) && searchResponse.getHits().getTotalHits() > 0) {
+            SearchHits hits = searchResponse.getHits();
+            for (SearchHit hit : hits) {
+                /*将 JSON 转换成对象*/
+                T bean = JSON.parseObject(hit.getSourceAsString(), beanClass);
+                list.add(bean);
+            }
+        }
+    }
+}

+ 35 - 0
4dkankan-utils-pdf/pom.xml

@@ -0,0 +1,35 @@
+<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>4dkankan-utils</artifactId>
+        <groupId>com.fdkankan</groupId>
+        <version>3.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>4dkankan-utils-pdf</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.aspose</groupId>
+            <artifactId>aspose-cells</artifactId>
+            <version>22.7</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>8</source>
+                    <target>8</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 1 - 0
pom.xml

@@ -26,6 +26,7 @@
         <module>4dkankan-utils-wechat</module>
         <module>4dkankan-utils-image</module>
         <module>4dkankan-utils-sensitive-word</module>
+        <module>4dkankan-utils-elasticsearch</module>
     </modules>
 
     <groupId>com.fdkankan</groupId>