Spring Boot整合Elasticsearch(SearchSourceBuilder、BoolQueryBuilder、RestHighLevelClient的使用)
1、maven引入
(version版本需要与es的版本一致)
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.3.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.3.0</version>
</dependency>
2、es全文检索全局配置
import lombok.extern.slf4j.Slf4j;
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
@Slf4j
public class ElasticsearcConfig {
@Value("${elasticsearc.host}")
public String host;
@Value("${elasticsearc.port}")
public String port;
@Bean(destroyMethod = "close")
public RestHighLevelClient client() {
log.info("正在获得Elasticsearc配置信息");
return new RestHighLevelClient(RestClient.builder(new HttpHost(host, Integer.parseInt(port), "http")));
}
}
配置文件 (按照自己es库的地址配置)
elasticsearc:
host: 192.168.1.104
port: 19200
3、es操作的工具类util
1、分页对象TableDataInfo:
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.List;
/**
* 表格分页数据对象
*/
@ApiModel("列表数据")
public class TableDataInfo<T> implements Serializable
{
private static final long serialVersionUID = 1L;
/** 总记录数 */
@ApiModelProperty("数据总条数")
private long total;
/** 列表数据 */
@ApiModelProperty("列表数据")
private List<T> rows;
/** 消息状态码 */
@ApiModelProperty("消息状态码")
private int code;
/** 消息内容 */
private String msg;
/**
* 表格数据对象
*/
public TableDataInfo()
{
}
/**
* 分页
*
* @param list 列表数据
* @param total 总记录数
*/
public TableDataInfo(List<T> list, int total)
{
this.rows = list;
this.total = total;
}
public long getTotal()
{
return total;
}
public void setTotal(long total)
{
this.total = total;
}
public List<?> getRows()
{
return rows;
}
public void setRows(List<T> rows)
{
this.rows = rows;
}
public int getCode()
{
return code;
}
public void setCode(int code)
{
this.code = code;
}
public String getMsg()
{
return msg;
}
public void setMsg(String msg)
{
this.msg = msg;
}
}
2、es工具类 ESUtils:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
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.client.indices.GetIndexResponse;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @title: ES工具类
**/
public class ESUtils {
/**
* id
**/
private static final String ID = "id";
/**
* @title: 添加Documents
*/
public static IndexResponse insertDoc(RestHighLevelClient client, String index, Map<String, Object> bean) throws IOException {
IndexRequest request;
if (bean.containsKey(ID)) {
request = new IndexRequest(index).id(bean.get(ID).toString()).source(bean);
} else {
request = new IndexRequest(index).source(bean);
}
return client.index(request, RequestOptions.DEFAULT);
}
/**
* @title: 批量添加Documents
*/
public static <T> BulkResponse batchInsertDoc(RestHighLevelClient client, String index, List<T> beanList) throws IOException {
BulkRequest request = new BulkRequest();
List<Map<String, Object>> mapList = beanList.stream().map(model -> Utils.beanToMap(model)).collect(Collectors.toList());
for (Map<String, Object> bean : mapList) {
IndexRequest indexRequest;
if (bean.containsKey(ID)) {
indexRequest = new IndexRequest(index).id(bean.get(ID).toString()).source(bean);
} else {
indexRequest = new IndexRequest(index).source(bean);
}
request.add(indexRequest);
}
//客户端发送请求,获取响应对象
BulkResponse responses = client.bulk(request, RequestOptions.DEFAULT);
return responses;
}
/**
* @title: 修改Documents
*/
public static UpdateResponse updateDoc(RestHighLevelClient client, String index, String id, Object bean) throws IOException {
UpdateRequest request = new UpdateRequest(index, id);
//保证数据实时更新
request.timeout("1s");
request.doc(JSON.toJSONString(bean), XContentType.JSON);
return client.update(request, RequestOptions.DEFAULT);
}
/**
* @title: 删除Documents
*/
public static DeleteResponse deleteDoc(RestHighLevelClient client, String index, String id) throws IOException {
DeleteRequest request = new DeleteRequest(index, id);
//保证数据实时更新
request.timeout("1s");
return client.delete(request, RequestOptions.DEFAULT);
}
/**
* @title: 批量删除Documents
*/
public static BulkResponse batchDeleteDoc(RestHighLevelClient client, String index, List<String> ids) throws IOException {
//创建批量删除请求对象
BulkRequest request = new BulkRequest();
for (String id : ids) {
request.add(new DeleteRequest().index(index).id(id));
}
//客户端发送请求,获取响应对象
BulkResponse responses = client.bulk(request, RequestOptions.DEFAULT);
return responses;
}
/**
* @title: 查询列表
*/
public static <T> TableDataInfo searchListPage(RestHighLevelClient client,
String index,
SearchSourceBuilder searchSourceBuilder,
Class<T> clazz) throws IOException {
List<T> list = new LinkedList<>();
// 创建查询请求
SearchRequest searchRequest = new SearchRequest(index);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHit[] hits = response.getHits().getHits();
Long total = response.getHits().getTotalHits().value;
for (SearchHit hit : hits) {
T entity = JSONObject.parseObject(hit.getSourceAsString(), clazz);
list.add(entity);
}
TableDataInfo result = new TableDataInfo(list, total.intValue());
return result;
}
/**
* @title: 查询列表
*/
public static <T> List searchList(RestHighLevelClient client,
String[] index,
SearchSourceBuilder searchSourceBuilder,
Class<T> clazz) throws IOException {
List<T> list = new LinkedList<>();
// 创建查询请求
SearchRequest searchRequest = new SearchRequest(index, new SearchSourceBuilder());
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHit[] hits = response.getHits().getHits();
Long total = response.getHits().getTotalHits().value;
for (SearchHit hit : hits) {
T entity = JSONObject.parseObject(hit.getSourceAsString(), clazz);
list.add(entity);
}
return list;
}
/**
* @title: 查询一个
*/
public static <T> T searchOne(RestHighLevelClient client, String index, String id, Class<T> clazz) throws IOException {
//1.创建请求对象
GetRequest request = new GetRequest().index(index).id(id);
//2.客户端发送请求,获取响应对象
GetResponse response = client.get(request, RequestOptions.DEFAULT);
return JSONObject.parseObject(response.getSourceAsString(), clazz);
}
/**
* @title: 创建索引
*/
public static boolean createIndex(RestHighLevelClient client, String index) {
// 创建索引 - 请求对象
CreateIndexRequest request = new CreateIndexRequest(index);
//设置默认size最大值
Settings.Builder builder = Settings.builder().put("max_result_window", 100000);
request.settings(builder);
// 发送请求,获取响应
CreateIndexResponse response = null;
try {
response = client.indices().create(request, RequestOptions.DEFAULT);
// 响应状态
boolean acknowledged = response.isAcknowledged();
return acknowledged;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* @title: 查询是否存在索引
*/
public static boolean existsIndex(RestHighLevelClient client, String index) {
// 查询索引 - 请求对象
GetIndexRequest request = new GetIndexRequest(index);
// 发送请求,获取响应
try {
GetIndexResponse response = client.indices().get(request, RequestOptions.DEFAULT);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 设置索引参数
*
* @param client
* @param indexs
* @return
*/
public static boolean putIndexSetting(RestHighLevelClient client, String[] indexs, Settings builder) {
try {
//创建Setting对象
// Settings settings = Settings.builder()
// .put("max_result_window", 100000).build();//es默认是1000
for (String index : indexs) {
UpdateSettingsRequest request = new UpdateSettingsRequest(builder, index);
AcknowledgedResponse response = client.indices().putSettings(request, RequestOptions.DEFAULT);
}
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
}
3、Utils工具类
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class Utils {
/* 对象转map */
public static <T> Map<String, Object> beanToMap(T bean) {
Map<String, Object> map = new HashMap<>(16);
if (bean != null) {
Class<?> aClass = bean.getClass();
BeanMap beanMap = BeanMap.create(bean);
for (Object key : beanMap.keySet()) {
if (beanMap.get(key) != null) {
if (beanMap.get(key).getClass() == Timestamp.class) {
Timestamp time = (Timestamp) beanMap.get(key);
Date date = new Date(time.getTime());
map.put(key + "", date);
continue;
}
map.put(key + "", beanMap.get(key));
}
}
}
return map;
}
}
4、使用
@Resource
private RestHighLevelClient client;
public List<Map<String, Object>> getEsData() {
//比如需要查询的语句在Sql :
// select * from [table] t
// where (t.pdtFactorCode = a or t.pdtFactorCode = b)
// and (t.pdtMn = c or t.pdtMn = d)
// and t.pdtDatetime > startTime and t.pdtDatetime <= endTime
//那么在代码中:
// 创建查询构造
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 分页获取最大total数时正常显示
searchSourceBuilder.trackTotalHits(true);
// 条件查询
BoolQueryBuilder qbEnd = QueryBuilders.boolQuery();
//1、设置 FactorCode 查询条件
BoolQueryBuilder qbFactorCodeSet = QueryBuilders.boolQuery();
//.should() 代表 or
qbFactorCodeSet.should().add(QueryBuilders.termQuery("pdtFactorCode.keyword", a));
qbFactorCodeSet.should().add(QueryBuilders.termQuery("pdtFactorCode.keyword", b));
//2、设置 mn 查询条件
BoolQueryBuilder qbMnSet = QueryBuilders.boolQuery();
//.should() 代表 or
qbMnSet.should().add(QueryBuilders.termQuery("pdtMn.keyword", c));
qbMnSet.should().add(QueryBuilders.termQuery("pdtMn.keyword", d));
//开始结束时间 根据需求设置
long startL = 9662447600000L;
long endL = 0L;
//3、设置 时间范围
//.rangeQuery() 表示范围查询
// .must() 表示 and
qbEnd.must().add(QueryBuilders.rangeQuery("pdtDatetime")
.gte(startL)
.lte(endL));
//将查询条件加入
qbEnd.must().add(qbFactorCodeSet);
qbEnd.must().add(qbMnSet);
searchSourceBuilder.query(qbEnd);
searchSourceBuilder.size(100000);
//设置需要查询的index
String[] indexArray = {"index1","index2"}
List<Map<String, Object>> dataList = new ArrayList<>();
try {
dataList = ESUtils.searchList(client, indexArray, searchSourceBuilder, Map.class);
} catch (Exception e) {
e.printStackTrace();
}
return dataList;
}
SearchSourceBuilder 和 BoolQueryBuilder 的更多使用方法,可以看看源码 或者搜一下对应的文章,可参考:https://www.cnblogs.com/xiaofeng-fu/p/14075446.html
参考文章:
www.cnblogs.com/xiaofeng-fu/p/14075446.html
cloud.tencent.com/developer/article/1786808
www.jianshu.com/p/b0197c6ff895