教程
https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.14/java-rest-high.html
https://blog.csdn.net/XJ0927/article/details/111999742
https://blog.csdn.net/Koikoi12/article/details/120182936
添加依赖
<properties>
<!-- 统一版本 -->
<elasticsearch.version>7.14.2</elasticsearch.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
</dependencies>
配置接入信息
spring:
elasticsearch:
uris: http://172.0.0.1:9200
username: elastic
password: xxxxxxxxxx
工具类
注意不同客户端版本的接口有所不同;当前对接的是7.14版本的Java High Level REST Client.
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.model.es.ESGamerTitle;
import com.ruoyi.common.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
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.WriteRequest;
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.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.core.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Component;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* ES工具类
* <p>
* es的index == mysql的database-table
* es的document == mysql的row
* es的field == mysql的column
* <p>
* GET http:// == select * from table...
* PUT http:// == update table set...
*
* 修改数据后需要设置刷新策略为立即刷新,否则数据刷新有延迟
* 刷新索引的策略:NONE(“false”)、IMMEDIATE(“true”)、WAIT_UNTIL(“wait_for”)
*
*/
@Component
@RequiredArgsConstructor
@Slf4j
public class ESUtil {
private final RestHighLevelClient client;
/**
* 设置超时时间为1s
*/
public final static TimeValue timeValue = TimeValue.timeValueSeconds(1);
/**
* 设置请求方式为默认
*/
public final static RequestOptions requestOptions = RequestOptions.DEFAULT;
/**
* index列表
*/
public final static String GAMER_TITLE_INDEX = "gamer-title-index";
public final static String ROOM_TITLE_INDEX = "room-title-index";
public final static String GAMER_BAG_INDEX = "gamer-bag-index";
public final static String TROUBLE_RANK_INDEX = "trouble-rank-index";
// public final static String GIFT_RECORD_INDEX = "gift-record-index";
// public final static String COMMENTS_INDEX = "comments-index";
/**
* 创建索引
*
* @param index 索引名
* @return 是否成功
*/
@SneakyThrows
public boolean createIndex(String index) {
CreateIndexRequest request = new CreateIndexRequest(index);
CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
log.info("ES创建索引={}, 返回={}", index, JSONUtil.toJsonStr(response));
return response.isAcknowledged();
}
/**
* 查询索引是否存在
*
* @param index 索引名
* @return 是否成功
*/
@SneakyThrows
public boolean existIndex(String index) {
GetIndexRequest request = new GetIndexRequest(index);
boolean exists = client.indices().exists(request, requestOptions);
log.info("ES查询索引是否存在={}, 返回={}", index, exists);
return exists;
}
/**
* 删除索引
*
* @param index 索引名
* @return 是否成功
*/
@SneakyThrows
public boolean delIndex(String index) {
DeleteIndexRequest request = new DeleteIndexRequest(index);
AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
log.info("ES删除索引={}, 返回={}", index, JSONUtil.toJsonStr(response));
return response.isAcknowledged();
}
/**
* 增加文档
*
* @param index 索引名
* @param id 文档id 为空则自动创建id
* @param json 文档jsonstr
* @return 是否成功
*/
@SneakyThrows
public boolean addDocument(String index, String id, String json) {
IndexRequest request = new IndexRequest(index);
if (StrUtil.isNotBlank(id)) {
request.id(id);
}
request.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
request.source(json, XContentType.JSON);
request.timeout(timeValue);
IndexResponse response = client.index(request, requestOptions);
log.info("ES增加文档={}, id={}, json={}, 返回={}", index, id, json, JSONUtil.toJsonStr(response));
return response.status().name().equals("CREATED");
}
/**
* 更新文档
*
* @param index 索引名
* @param id 文档id
* @param json 文档jsonstr
* @return 是否成功
*/
@SneakyThrows
public boolean updateDocument(String index, String id, String json) {
IndexRequest request = new IndexRequest(index).id(id).source(json,XContentType.JSON);
request.timeout(timeValue);
request.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
IndexResponse response = client.index(request, requestOptions);
log.info("ES更新文档={}, id={}, 返回={}", index, id, JSONUtil.toJsonStr(response));
return response.status().name().equals("OK");
}
/**
* 删除文档
*
* @param index 索引名
* @param id 文档id
* @return 是否成功
*/
@SneakyThrows
public boolean delDocument(String index, String id) {
DeleteRequest request = new DeleteRequest(index, id);
request.timeout(timeValue);
request.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
DeleteResponse response = client.delete(request, requestOptions);
log.info("ES删除文档={}, id={}, 返回={}", index, id, JSONUtil.toJsonStr(response));
return response.status().name().equals("OK");
}
/**
* 查询文档
*
* @param index 索引名
* @param id 文档id
* @return json 文档jsonstr
*/
@SneakyThrows
public GetResponse getDocument(String index, String id) {
GetRequest request = new GetRequest(index, id);
GetResponse response = client.get(request, RequestOptions.DEFAULT);
log.info("ES查询文档={}, id={}, 返回={}", index, id, JSONUtil.toJsonStr(response));
return response;
}
/**
* 查询文档列表
*
* @param index 索引名
* @param map 匹配条件 不能为空 全等
* @return json 文档jsonstr
*/
@SneakyThrows
public SearchHit[] getDocuments(String index, Map<String, Object> map) {
SearchRequest request = new SearchRequest(index);
SearchSourceBuilder builder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
Iterator<Map.Entry<String, Object>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> next = iterator.next();
boolQuery.filter(QueryBuilders.termQuery(next.getKey(), next.getValue()));
builder.query(boolQuery);
}
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
log.info("ES查询文档列表={}, map={}, 返回={}", index, JSONUtil.toJsonStr(map), JSONUtil.toJsonStr(response));
return response.getHits().getHits();
}
/**
* 排序设置大小 查询文档列表
*
* @param index 索引名
* @param map 匹配条件 不能为空 全等
* @return json 文档jsonstr
*/
@SneakyThrows
public SearchHit[] getDocuments(String index, Map<String, Object> map, String sortField, Integer size) {
SearchRequest request = new SearchRequest(index);
SearchSourceBuilder builder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
Iterator<Map.Entry<String, Object>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> next = iterator.next();
boolQuery.filter(QueryBuilders.termQuery(next.getKey(), next.getValue()));
builder.query(boolQuery);
}
builder.sort(sortField, SortOrder.DESC);
builder.size(size);
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
log.info("ES查询文档列表排序={}, map={}, 返回={}", index, JSONUtil.toJsonStr(map), JSONUtil.toJsonStr(response));
return response.getHits().getHits();
}
/**
* 查询文档
*
* @param index 索引名
* @param map 匹配条件 不能为空 全等
* @return json 文档jsonstr
*/
@SneakyThrows
public SearchHit findOne(String index, Map<String, Object> map) {
SearchRequest request = new SearchRequest(index);
SearchSourceBuilder builder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
Iterator<Map.Entry<String, Object>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> next = iterator.next();
boolQuery.filter(QueryBuilders.termQuery(next.getKey(), next.getValue()));
builder.query(boolQuery);
}
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
log.info("ES查询文档列表={}, map={}, 返回={}", index, JSONUtil.toJsonStr(map), JSONUtil.toJsonStr(response));
if (response.getHits().getHits() == null || response.getHits().getHits().length == 0) {
return null;
} else {
return response.getHits().getHits()[0];
}
}
/**
* 更新玩家佩戴的称号 有问题
*
* @param index
* @param map
* @return
*/
@SneakyThrows
public void updateGamerWearTitle(String index, Map<String, Object> map) {
SearchHit[] hits = getDocuments(index, map);
if (hits == null || hits.length == 0){
return;
}
BulkRequest request = new BulkRequest();
for (int i = 0; i < hits.length; i++) {
ESGamerTitle title = JSONUtil.toBean(hits[i].getSourceAsString(), ESGamerTitle.class);
title.setWear(false);
request.add(new UpdateRequest().id(hits[i].getId()).doc(JSONUtil.toJsonStr(title)));
}
BulkResponse response = client.bulk(request, requestOptions);
log.info("ES按条件更新文档={}, map={}, 返回={}", index, JSONUtil.toJsonStr(map), JSONUtil.toJsonStr(response));
}
/**
* 按条件删除文档
*
* @param index
* @param map
* @return
*/
@SneakyThrows
public void delByMap(String index, Map<String, Object> map) {
DeleteByQueryRequest request = new DeleteByQueryRequest(index);
Iterator<Map.Entry<String, Object>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> next = iterator.next();
request.setQuery(QueryBuilders.termQuery(next.getKey(), next.getValue()));
}
request.setRefresh(true);
BulkByScrollResponse response = client.deleteByQuery(request, requestOptions);
log.info("ES按条件删除文档={}, map={}, 返回={}", index, JSONUtil.toJsonStr(map), JSONUtil.toJsonStr(response));
}
public void insertOrUpdateOne(String index, String id, String data) {
IndexRequest request = new IndexRequest(index);
request.id(id);
request.source(data, XContentType.JSON);
try {
client.index(request, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("error save info", e);
}
}
public void updateOne(String index, String id, Map<String, Object> map) {
UpdateRequest updateRequest = new UpdateRequest(index, id);
updateRequest.doc(map);
try {
UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
log.info("updateOne result:{}", JSON.toJSONString(updateResponse));
} catch (Exception e) {
log.warn("updateOne to ES Exception : ", e);
throw new RuntimeException(e);
}
}
/**
* 批量插入文档
*
* @param index ES索引
* @param documents 待提交的批量文档
* @param uuidKey 文档中ID字段对应的key值
*/
public BulkResponse insertDocumentsAsBatch(String index, List<Map<String, Object>> documents, String uuidKey) {
BulkResponse response = null;
if (StringUtils.isBlank(index) || CollectionUtils.isEmpty(documents)) {
log.warn("Es index is blank or documents is empty.");
return response;
}
try {
BulkRequest bulkRequest = new BulkRequest();
for (Map<String, Object> document : documents) {
if (MapUtils.isEmpty(document) || !document.containsKey(uuidKey)) {
continue;
}
bulkRequest.add(new IndexRequest(index).opType("create").id(document.get(uuidKey).toString()).source(document));
}
response = client.bulk(bulkRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("Insert documents to es as batch failed!", e);
}
return response;
}
/**
* 批量更新文档
*
* @param index ES索引
* @param documents 待提交的批量文档
* @param uuidKey 文档中ID字段对应的key值
*/
public BulkResponse updateDocumentsAsBatch(String index, List<Map<String, Object>> documents, String uuidKey) {
BulkResponse response = null;
if (StringUtils.isBlank(index) || CollectionUtils.isEmpty(documents)) {
log.warn("Es index is blank or documents is empty.");
return response;
}
try {
BulkRequest bulkRequest = new BulkRequest();
for (Map<String, Object> document : documents) {
if (MapUtils.isEmpty(document) || !document.containsKey(uuidKey)) {
continue;
}
bulkRequest.add(new UpdateRequest(index, document.get(uuidKey).toString()).doc(document));
}
response = client.bulk(bulkRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("Update documents to es as batch failed!", e);
}
return response;
}
/**
* 批量删除多个文档数组
*
* @param index ES索引
* @param documents 待提交的批量文档
* @param uuidKey 文档中ID字段对应的key值
*/
public BulkResponse deleteDocumentsAsBatch(String index, List<Map<String, Object>> documents, String uuidKey) {
BulkResponse response = null;
if (StringUtils.isBlank(index) || CollectionUtils.isEmpty(documents)) {
log.warn("Es index is blank or documents is empty.");
return response;
}
try {
BulkRequest bulkRequest = new BulkRequest();
for (Map<String, Object> document : documents) {
if (MapUtils.isEmpty(document) || !document.containsKey(uuidKey)) {
continue;
}
bulkRequest.add(new DeleteRequest(index, document.get(uuidKey).toString()));
}
response = client.bulk(bulkRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("Update documents to es as batch failed!", e);
}
return response;
}
}