我的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索引以及文档的操作了。
有好的建议,请在下方输入你的评论。