Elasticsearch(八)SpringBoot集成Elasticsearch

150 阅读5分钟

我的PHP版本博客使用的全文检索是sphinxfochinese,java版本博客要使用我们研究了好几天的Elasticsearch。

 

那么我需要将Elasticsearch集成到Springboot框架中。

 

一:添加依赖

在pom.xml中添加

<properties>
     <java.version>11</java.version>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
     <spring-boot.version>2.6.13</spring-boot.version>
     <!-- 统一版本 -->
     <elasticsearch.version>7.17.3</elasticsearch.version>
 </properties>
<!-- elasticsearch       -->
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
 </dependency>

 

二:添加配置

在yml文件中添加如下配置:

spring:
   # elasticsearch 配置
   elasticsearch:
     ip: 1.15.157.156
     port: 9200
     protocol: http

 

三:创建并编写配置类

在config目录下添加ElasticSearchConfig.java文件

package com.springbootblog.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;
 
 @Configuration
 public class ElasticSearchConfig
 {
     @Value("${spring.elasticsearch.ip}")
     private String hostname;
 
     @Value("${spring.elasticsearch.port}")
     private Integer port;
 
     @Value("${spring.elasticsearch.protocol}")
     private String protocol;
 
     // 注册 rest高级客户端
     @Bean
     public RestHighLevelClient restHighLevelClient()
     {
         // System.out.println(hostname);
         // System.out.println(port);
         // System.out.println(protocol);
         RestHighLevelClient client = new RestHighLevelClient(
                 RestClient.builder(
                         new HttpHost(hostname, port, protocol)
                 )
         );
         return client;
     }
 }

四:创建工具类

在utils目录下创建工具类ElasticsearchUtils.java

package com.springbootblog.utils;
 
 import com.alibaba.fastjson.JSON;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
 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.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.common.text.Text;
 import org.elasticsearch.common.xcontent.XContentType;
 import org.elasticsearch.core.TimeValue;
 import org.elasticsearch.index.query.BoolQueryBuilder;
 import org.elasticsearch.index.query.MultiMatchQueryBuilder;
 import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.search.SearchHit;
 import org.elasticsearch.search.SearchHits;
 import org.elasticsearch.search.builder.SearchSourceBuilder;
 import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
 import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
 import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
 import org.jetbrains.annotations.NotNull;
 
 import java.io.IOException;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 
 public class ElasticsearchUtils
 {
     // ==========================================================================================================
     // 索引操作 start
     /**
      * 创建索引
      * @param restHighLevelClient
      * @throws IOException
      */
     public static @NotNull Map<String, Object> createIndex(RestHighLevelClient restHighLevelClient, String indexName) throws IOException
     {
         Map<String,Object> result = new HashMap<>(2);
         try
         {
             CreateIndexRequest request = new CreateIndexRequest(indexName);
             CreateIndexResponse response = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
             // 查看是否创建成功
             if(!response.isAcknowledged())
             {
                 result.put("code", -1);
                 result.put("msg""创建失败!");
                 return result;
             }
             // 查看返回对象
             // System.out.println(response);
             restHighLevelClient.close();
             result.put("code"1);
             result.put("msg""操作成功!");
             return result;
         }
         catch (Exception ex)
         {
             result.put("code", -2);
             result.put("msg""创建失败!");
             return result;
         }
     }
 
     /**
      * 获取索引,并判断其是否存在
      * @param restHighLevelClient
      * @throws IOException
      */
     public static @NotNull Map<String, Object> indexIsExists(RestHighLevelClient restHighLevelClient, String indexName) throws IOException
     {
         Map<String,Object> result = new HashMap<>(3);
         try
         {
             GetIndexRequest request = new GetIndexRequest(indexName);
             boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
             // 索引是否存在
             System.out.println(exists);
             restHighLevelClient.close();
             result.put("code"1);
             result.put("msg""操作成功!");
             result.put("exists", exists);
             return result;
         }
         catch (Exception ex)
         {
             System.out.println(indexName);
             result.put("code"2);
             result.put("msg""操作成功!");
             result.put("exists"false);
             return result;
         }
 
     }
 
     /**
      * 索引删除
      * @param restHighLevelClient
      * @param indexName
      * @throws IOException
      */
     public static @NotNull Map<String, Object> deleteIndex(RestHighLevelClient restHighLevelClient, String indexName) throws IOException
     {
         Map<String,Object> result = new HashMap<>(2);
         try
         {
             DeleteIndexRequest request = new DeleteIndexRequest(indexName);
             AcknowledgedResponse response = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
             // 是否删除成功
             // System.out.println(response.isAcknowledged());
             if(!response.isAcknowledged())
             {
                 result.put("code", -2);
                 result.put("msg""删除失败!");
                 return result;
             }
             restHighLevelClient.close();
             result.put("code"1);
             result.put("msg""操作成功!");
             return result;
         }
         catch (Exception ex)
         {
             result.put("code", -1);
             result.put("msg""系统错误,删除失败!");
             return result;
         }
     }
 
     // ==========================================================================================================
     // 文档操作 start
     // 添加文档(先创建一个User实体类,添加fastjson依赖)
     /**
      * 单个添加文档
      * @param object                实体类对象
      * @param indexName             索引名称
      * @param restHighLevelClient   Elasticsearch对象
      * @throws IOException
      */
     public static @NotNull Map<String, Object> addDocument(Object object, String indexName, RestHighLevelClient restHighLevelClient, String id, String time) throws IOException
     {
         Map<String,Object> result = new HashMap<>(2);
         try
         {
             // 创建请求 添加文档请求
             IndexRequest request = new IndexRequest(indexName);
             // 制定规则 PUT /liuyou_index/_doc/1
             // 设置文档ID
             request.id(id);
             // 设置 超时时间
             request.timeout(time); //request.timeout(TimeValue.timeValueMillis(1000));
             // 将我们的数据放入请求中
             request.source(JSON.toJSONString(object), XContentType.JSON);
             // 客户端发送请求,获取响应的结果
             IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
             // 获取建立索引的状态信息 CREATED
             System.out.println(response.status());
             // 查看返回内容 IndexResponse[index=liuyou_index,type=_doc,id=1,version=1,result=created,seqNo=0,primaryTerm=1,shards={"total":2,"successful":1,"failed":0}]
             System.out.println(response);
             result.put("code"1);
             result.put("msg""操作成功!");
             return result;
         }
         catch(Exception ex)
         {
             result.put("code", -1);
             result.put("msg""系统错误,添加失败!");
             return result;
         }
     }
 
     /**
      * 文档信息的获取 根据 id
      * @param restHighLevelClient
      * @param indexName
      * @param id
      * @throws IOException
      */
     public static @NotNull Map<String, Object> getDocument(RestHighLevelClient restHighLevelClient, String indexName, String id) throws IOException
     {
         Map<String,Object> result = new HashMap<>(2);
         try
         {
             GetRequest request = new GetRequest(indexName,id);
             GetResponse response = restHighLevelClient.get(request, RequestOptions.DEFAULT);
             // 打印文档内容
             System.out.println("getSourceAsString:"+response.getSourceAsString());
             // 返回的全部内容和命令是一样的
             System.out.println("request:"+request);
             restHighLevelClient.close();
             result.put("code"1);
             result.put("object", response.getSourceAsString());
             return result;
         }
         catch(Exception ex)
         {
             result.put("code", -1);
             result.put("msg""系统错误,获取失败!");
             return result;
         }
     }
 
 
     /**
      * 获取文档,判断是否存在 get /liuyou_index/_doc/1
      * @param restHighLevelClient
      * @param indexName
      * @param id
      * @throws IOException
      */
     public static @NotNull Map<String, Object> documentIsExists(RestHighLevelClient restHighLevelClient, String indexName, String id) throws IOException
     {
         Map<String,Object> result = new HashMap<>(2);
         try
         {
             GetRequest request = new GetRequest(indexName, id);
             // 不获取返回的 _source的上下文了
             request.fetchSourceContext(new FetchSourceContext(false));
             request.storedFields("_none_");
             boolean exists = restHighLevelClient.exists(request, RequestOptions.DEFAULT);
             System.out.println("exists:"+exists);
             result.put("code"1);
             result.put("exists", exists);
             return result;
         }
         catch(Exception ex)
         {
             result.put("code", -1);
             result.put("msg""系统错误!");
             return result;
         }
 
     }
 
     /**
      * 更新文档内容
      * @param restHighLevelClient
      * @param indexName
      * @param id
      * @param object
      * @throws IOException
      */
     public static @NotNull Map<String, Object> updateDocument(RestHighLevelClient restHighLevelClient, String indexName, String id, Object object) throws IOException
     {
         Map<String,Object> result = new HashMap<>(2);
         try
         {//*/
             UpdateRequest request = new UpdateRequest(indexName, id);
             request.timeout("60s");
             request.doc(JSON.toJSONString(object),XContentType.JSON);
             UpdateResponse response = restHighLevelClient.update(request, RequestOptions.DEFAULT);
             // 查看是否更新成功
             System.out.println(response.status());
             restHighLevelClient.close();
             result.put("code"1);
             result.put("status", response.status());
             return result;
         }
         catch(Exception ex)
         {
             result.put("code", -1);
             result.put("msg""系统错误!");
             return result;
         }//*/
     }
 
     /**
      * 删除文档
      * @param restHighLevelClient
      * @param indexName
      * @param id
      * @param time
      * @throws IOException
      */
     public static @NotNull Map<String, Object> deleteDocument(RestHighLevelClient restHighLevelClient, String indexName, String id, String time) throws IOException
     {
         Map<String,Object> result = new HashMap<>(2);
         try
         {
             DeleteRequest request = new DeleteRequest(indexName, id);
             request.timeout(time);
             DeleteResponse response = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
             // 查看是否删除成功 OK/NOT_FOUND
             System.out.println(response.status());
             result.put("code"1);
             result.put("status", response.status());
             return result;
         }
         catch(Exception ex)
         {
             result.put("code", -1);
             result.put("msg""系统错误!");
             return result;
         }
     }
 
     /**
      * 条件查询
      * @param restHighLevelClient
      * @param indexName
      * @param time
      * @throws IOException
      * SearchRequest 搜索请求
      * SearchSourceBuilder 条件构造
      * HighlightBuilder 高亮
      * TermQueryBuilder 精确查询
      * MatchAllQueryBuilder
      * xxxQueryBuilder ...
      */
     public static Map<String, Object> mapSearch(@NotNull RestHighLevelClient restHighLevelClient, String indexName, Long time, String searchString,Integer page, String[] field) throws IOException
     {
         Map<String,Object> result = new HashMap<>(6);
         /*try
         {//*/
             // 1.创建查询请求对象
             SearchRequest searchRequest = new SearchRequest(indexName);
             // 2.构建搜索条件
             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
             // (1)查询条件 使用QueryBuilders工具类创建
             // 精确查询
             // TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "liuyou");
             // 匹配查询
             // MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
             // System.out.println(searchString);
             // 单字段 匹配查询
             // MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("content",searchString);
             // 多字段查询
             BoolQueryBuilder matchQueryBuilder = QueryBuilders.boolQuery();
 
             for (String item : field) {
                 matchQueryBuilder.should(QueryBuilders.matchQuery(item, searchString));
             }
             // 设置循环中每个字段的权重,这里所有字段权重相同
             matchQueryBuilder.minimumShouldMatch(1);
             // MultiMatchQueryBuilder matchQueryBuilder = QueryBuilders.multiMatchQuery(searchString,"content","arttitle","artdesc");
             // 分页
             Integer pageSize = 9;
             // 计算分页信息
             Map<String, Integer> pageInfo = Function.getStartNumByPage(page, pageSize);
             Integer startPage = pageInfo.get("page");
             Integer showNum = pageInfo.get("pageSize");
             // elasticsearch 分页
             searchSourceBuilder.from(startPage);
             searchSourceBuilder.size(showNum);
             searchSourceBuilder.timeout(new TimeValue(time, TimeUnit.SECONDS));
             // searchSourceBuilder.timeout(time);
             // (2)其他<可有可无>:(可以参考 SearchSourceBuilder 的字段部分)
             // 设置高亮
             HighlightBuilder highlightBuilder = new HighlightBuilder();
             // 循环高亮字段
             for (String s : field)
             {
                 highlightBuilder.field(s);
             }
             // 设置高亮标签
             highlightBuilder.preTags("<font style='color:red;'>").postTags("</font>");
             searchSourceBuilder.highlighter(highlightBuilder);
 
             // (3)条件投入
             searchSourceBuilder.query(matchQueryBuilder);
             // 3.添加条件到请求
             searchRequest.source(searchSourceBuilder);
             // 4.客户端查询请求
             SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
             // 5.查看返回结果
             SearchHits hits = search.getHits();
             // 6.获取查询结果集总数(未分页的情况下)
             long number = hits.getTotalHits().value;
             // 页码数
             int articleNum = (int) (Math.ceil((float)number / (float)pageSize) - 1) + 1;
             // 高亮字段 解析结果
             List<Object> list = new ArrayList<>();
             for (SearchHit hit: hits.getHits())
             {
                 //解析高亮字段
                 Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                 //System.out.println(hit);
                 //获取原字段
                 Map<String, Object> oldUser = hit.getSourceAsMap();
                 //将高亮替换原字段内容
                 StringBuilder stringBuilder = new StringBuilder();
                 // ================================================================
                 // 第一个高亮字段
                 HighlightField arttitle = highlightFields.get("arttitle");
                 if (arttitle!=null)
                 {
                     Text[] texts = arttitle.fragments();
                     for (Text t:texts)
                     {
                         stringBuilder.append(t);
                     }
                     oldUser.put("arttitle",stringBuilder.toString());
                 }
                 // ================================================================
                 // 第二个高亮字段
                 HighlightField artdesc = highlightFields.get("artdesc");
                 if (artdesc!=null)
                 {
                     Text[] texts = artdesc.fragments();
                     for (Text t:texts)
                     {
                         stringBuilder.append(t);
                     }
                     oldUser.put("artdesc",stringBuilder.toString());
                 }
                 list.add(oldUser);
             }//*/
             result.put("code"1);
             result.put("msg""操作成功!");
             result.put("articleShow", list);
             result.put("cateName", searchString);
             result.put("articlePage", articleNum);
             result.put("cateList"new ArrayList<String>());
             return result;
         /*}
         catch(Exception ex)
         {
             result.put("code", -1);
             result.put("msg", "系统错误!");
             return result;
         }//*/
     }
 
     /**
      * elasticsearch 批量插入数据
      * @param restHighLevelClient
      * @param list
      * @param time
      * @throws IOException
      */
     public static Map<String,Object> batchAddData(RestHighLevelClient restHighLevelClient, @NotNull ArrayList<Map<String,Object>> list, String time, String indexName) throws IOException
     {
         BulkRequest bulkRequest = new BulkRequest();
         bulkRequest.timeout(time);
         // 批量请求处理
         for (int i = 0; i < list.size(); i++)
         {
             bulkRequest.add(
                     // 这里是数据信息
                     new IndexRequest(indexName)
                             .id(list.get(i).get("id").toString()) // 没有设置id 会自定生成一个随机id
                             .source(JSON.toJSONString(list.get(i).get("info")),XContentType.JSON)
             );
         }
         BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
         // 批量添加状态
         System.out.println(bulk.status());
         Map<String,Object> result = new HashMap<>(2);
         result.put("code"1);
         result.put("status", bulk.status());
         return result;
     }
 
 }

 

通过调用ElasticsearchUtils.java工具类即可实现对Elasticsearch索引以及文档的操作了。

 

有好的建议,请在下方输入你的评论。