一、使用原因
1.由於客戶要求,es要是用官方推薦elasticsearch-rest-high-level-client,原來用的是spring集成的感覺用着挺方便,換了jar後兩個jar不兼容,所以全部換成了elasticsearch-rest-high-level-client-6.5.0.jar(我們目前用的ES版本),但是用起來不是很方便,所以寫了一個工具類;
二、工具實例
1.1 client
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
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.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import java.io.Closeable;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 自定義es客戶端
*
* @author YanZhen
* @date 2019/10/23 12:17
**/
@Slf4j
public class CustomEsClient implements Closeable {
/**
* 默認超時時間
*/
private long timeOut = 1L;
/**
* RestHighLevelClient
*/
private RestHighLevelClient restHighLevelClient;
public CustomEsClient(RestHighLevelClient restHighLevelClient) {
this.restHighLevelClient = restHighLevelClient;
}
/**
* RestHighLevelClient
*
* @return 獲取RestHighLevelClient實例
*/
public RestHighLevelClient getRestHighLevelClient() {
return restHighLevelClient;
}
@Override
public void close() throws IOException {
restHighLevelClient.close();
}
/**
* 設置超時時間
*
* @param timeOut 超時時間,單位:秒
*/
public void setTimeOut(long timeOut) {
this.timeOut = timeOut;
}
/**
* 單條數據插入
*
* @param t 放入的對象
* @return 響應信息,放入es的基本信息(index、type、id)
*/
public IndexResponse add(EsIndexTypeId t) {
if (checkIndexTypeId(t)) {
return null;
}
String index = t.index();
String type = t.type();
String id = String.valueOf(t.id());
final String jsonString = JSONObject.toJSONString(t);
final IndexRequest request = new IndexRequest(index, type, id)
.source(jsonString, XContentType.JSON)
.opType(DocWriteRequest.OpType.CREATE)
.timeout(TimeValue.timeValueSeconds(timeOut));
IndexResponse indexResponse = null;
try {
indexResponse = restHighLevelClient.index(request, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("es(index:{},type:{},id:{})添加失敗:", index, type, id, e);
}
return indexResponse;
}
/**
* 批量數據插入
* 記錄是否有操作失敗的數據,請調用(BulkResponse.hasFailures)
*
* @param ts 放入的對象集合
* @return 響應信息,放入es的基本信息(index、type、id)
*/
public BulkResponse upsertAll(List<EsIndexTypeId> ts) {
BulkRequest bulkRequest = new BulkRequest();
IndexRequest request;
for (EsIndexTypeId t : ts) {
if (checkIndexTypeId(t)) {
continue;
}
final String jsonString = JSONObject.toJSONString(t);
request = new IndexRequest(t.index(), t.type(), String.valueOf(t.id()))
.source(jsonString, XContentType.JSON).timeout(TimeValue.timeValueSeconds(timeOut));
bulkRequest.add(request);
}
BulkResponse response = null;
try {
response = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("es批量添加失敗:", e);
}
return response;
}
/**
* 判斷索引是否存在
*
* @param t 與es存儲對應的對象
* @return true存在,false不存在
*/
public boolean existsIndex(EsIndexTypeId t) {
return existsIndex(t.index());
}
/**
* 判斷索引是否存在
*
* @param index 索引
* @return true存在,false不存在
*/
public boolean existsIndex(String index) {
if (index == null) {
return false;
}
GetIndexRequest request = new GetIndexRequest();
request.indices(index);
request.masterNodeTimeout(TimeValue.timeValueSeconds(timeOut));
boolean exists = false;
try {
exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("es(index:{})查詢異常:", index, e);
}
return exists;
}
/**
* 刪除單個數據
*
* @param t 與es存儲對應的對象,需要對象的(index、type、id)
* @return 刪除對象的基本信息(index 、 type 、 id)
*/
public DeleteResponse deleteById(EsIndexTypeId t) {
if (checkIndexTypeId(t)) {
return null;
}
DeleteRequest request = new DeleteRequest(t.index(), t.type(), String.valueOf(t.id()));
//設置超時:等待主分片變得可用的時間
request.timeout(TimeValue.timeValueMinutes(timeOut));
//同步執行
DeleteResponse deleteResponse = null;
try {
deleteResponse = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("es(index:{},type:{},id:{})刪除異常:", t.index(), t.type(), t.id(), e);
}
return deleteResponse;
}
/**
* 檢驗必要的值
*
* @param t 與es存儲對應的對象
* @return true不符合,false符合
*/
private boolean checkIndexTypeId(EsIndexTypeId t) {
return t == null || t.index() == null || t.type() == null || t.id() == null;
}
/**
* 刪除索引
*
* @param t 與es存儲對應的對象,需要對象的(index)
* @return 刪除索引的基本信息(index 、 type 、 id)
*/
public AcknowledgedResponse deleteIndex(EsIndexTypeId t) {
if (t == null || t.index() == null) {
return null;
}
return deleteIndex(t.index());
}
/**
* 刪除索引
*
* @param index 索引
* @return 刪除索引的基本信息(index 、 type 、 id)
*/
public AcknowledgedResponse deleteIndex(String index) {
if (index == null) {
return null;
}
DeleteIndexRequest request = new DeleteIndexRequest(index);
//設置超時:等待主分片變得可用的時間
request.timeout(TimeValue.timeValueMinutes(timeOut));
//同步執行
AcknowledgedResponse acknowledgedResponse = null;
try {
acknowledgedResponse = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("es(index:{})刪除索引異常:", index, e);
}
return acknowledgedResponse;
}
/**
* 根據ids批量刪除指定信息
* 記錄是否有操作失敗的數據,請調用(BulkResponse.hasFailures)
*
* @param index 索引
* @param type 索引指定的類型
* @param ids 要刪除的Id
* @return 刪除後響應信息
*/
public BulkResponse deleteByIds(String index, String type, List<Long> ids) {
if (index == null || type == null || ids == null || ids.isEmpty()) {
return null;
}
final BulkRequest request = new BulkRequest();
request.timeout(TimeValue.timeValueSeconds(timeOut));
DeleteRequest deleteRequest;
for (Long id : ids) {
deleteRequest = new DeleteRequest();
deleteRequest.index(index);
deleteRequest.type(type);
deleteRequest.id(id + "");
request.add(deleteRequest);
}
BulkResponse response = null;
try {
response = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("es(index:{},type:{},ids:{})刪除索引異常:", index, type, ids.toString(), e);
}
return response;
}
/**
* 根據不同的索引和類型和id批量刪除指定信息
* 記錄是否有操作失敗的數據,請調用(BulkResponse.hasFailures)
*
* @param ts 與es存儲對應的對象
* @return 刪除後響應信息
*/
public BulkResponse deleteByIndexAndTypeAndIds(List<EsIndexTypeId> ts) {
final BulkRequest request = new BulkRequest();
request.timeout(TimeValue.timeValueSeconds(timeOut));
DeleteRequest deleteRequest;
for (EsIndexTypeId t : ts) {
if (checkIndexTypeId(t)) {
continue;
}
deleteRequest = new DeleteRequest();
deleteRequest.index(t.index());
deleteRequest.type(t.type());
deleteRequest.id(t.id() + "");
request.add(deleteRequest);
}
BulkResponse response = null;
try {
response = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("es根據不同類型的索引刪除數據異常:", e);
}
return response;
}
/**
* 修改單條數據
*
* @param t 與es存儲對應的對象
* @return 響應修改對象的基本信息(index 、 type 、 id)
*/
public UpdateResponse update(EsIndexTypeId t) {
if (checkIndexTypeId(t)) {
return null;
}
UpdateRequest request = new UpdateRequest(t.index(), t.type(), String.valueOf(t.id()));
String jsonString = JSONObject.toJSONString(t);
request.upsert(jsonString, XContentType.JSON);
//設置超時:等待主分片變得可用的時間
request.timeout(TimeValue.timeValueSeconds(timeOut));
// 刷新
request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
//如果要更新的文檔在獲取或者索引階段已被另一操作更改,則重試更新操作的次數
request.retryOnConflict(3);
// 禁用noop檢測
request.detectNoop(false);
// 無論文檔是否存在,腳本都必須運行,即如果腳本尚不存在,則腳本負責創建文檔。
request.scriptedUpsert(false);
// 如果不存在,則表明部分文檔必須用作upsert文檔。
request.docAsUpsert(false);
request.doc(jsonString, XContentType.JSON);
//設置在繼續更新操作之前必須激活的分片副本的數量。
// request.waitForActiveShards(2);
//使用ActiveShardCount方式,可以是ActiveShardCount.ALL,ActiveShardCount.ONE或ActiveShardCount.DEFAULT(默認值)
// request.waitForActiveShards(ActiveShardCount.ALL);
//同步執行
UpdateResponse updateResponse = null;
try {
updateResponse = restHighLevelClient.update(request, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("es(index:{},type:{},id:{})更新異常:", t.index(), t.type(), t.id(), e);
}
return updateResponse;
}
/**
* 根據Id查詢數據
*
* @param t 與es存儲對應的對象
* @param tClass 與es存儲對應的對象的類型
* @return 響應信息
*/
public <T> T queryById(EsIndexTypeId t, Class<T> tClass) {
// 檢查參數
if (checkIndexTypeId(t)) {
return null;
}
// 根據ID查詢數據
final GetRequest getRequest = new GetRequest().index(t.index()).type(t.type()).id(String.valueOf(t.id()));
GetResponse documentFields = null;
try {
documentFields = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("es(index:{},type:{},id:{})根據文件Id查詢異常:", t.index(), t.type(), t.id(), e);
}
if (documentFields == null) {
return null;
}
return JSONObject.parseObject(documentFields.getSourceAsString(), tClass);
}
/**
* 查詢數據,帶分頁,且不指定分頁啓用默認值
* @param sourceBuilder 查詢條件
* @param index 索引
* @param type 索引類型
* @param tClass 返回對象類型
* @param <T> 返回對象類型
* @return 分頁數據
*/
public <T> PageEsData<T> searchPage(SearchSourceBuilder sourceBuilder, String index, String type, Class<T> tClass) {
// 校驗參數
if (sourceBuilder == null) {
return PageEsData.newPageData();
}
// 默認第0條開始
if (sourceBuilder.from() < 0) {
sourceBuilder.from(0);
}
// 默認一頁展示10條
if (sourceBuilder.size() < 1) {
sourceBuilder.size(10);
}
SearchResponse search = null;
try {
final SearchRequest request = new SearchRequest(index);
if (type != null) {
request.types(type);
}
sourceBuilder.timeout(TimeValue.timeValueSeconds(timeOut));
request.source(sourceBuilder);
search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("es(index:{},type:{})根據條件查詢異常:", index, type, e);
}
if (search == null) {
return null;
}
if (RestStatus.OK.getStatus() != search.status().getStatus()) {
log.warn("es(index:{},type:{})根據條件查詢失敗(狀態碼:{})", index, type, search.status().getStatus());
return PageEsData.newPageData();
}
// 響應數據
final SearchHits hits = search.getHits();
if (hits == null) {
return PageEsData.newPageData();
}
return new PageEsData<>(Arrays.stream(hits.getHits()).filter(Objects::nonNull)
.map(documentFields -> JSONObject.parseObject(documentFields.getSourceAsString(), tClass))
.collect(Collectors.toList()), hits.getTotalHits());
}
}
1.2 指定 索引、類型、ID的實體模板,存入es的實體需要實現這個接口模板
**
* @param <T> 對應實現類對象的ID類型,建議類型(Number、String)
* @author YanZhen
* @date 2019/10/23 13:50
**/
public interface EsIndexTypeId<T> {
/**
* 類型名,必須指定
* @return 該對象的索引
*/
String index();
/**
* 類型名,必須指定
* @return 該對象的類型
*/
String type();
/**
* 索引唯一id,必須指定
* @return 該對象的Id
*/
T id();
}
1.3 分頁對象,存放從es取出的實體並進行分頁
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;
import java.util.ArrayList;
import java.util.List;
/**
* ES分頁
*
* @author YanZhen
* @date 2019/10/24 13:47
**/
@ToString
@Data
@AllArgsConstructor
public class PageEsData<T> {
/**
* 響應信息
*/
private List<T> data;
/**
* 總數據數
*/
private long totalRows;
/**
* 獲取記錄開始行碼
*
* @param pageNum 當前頁數,從1開始
* @param pageSize 每頁顯示數
* @return 記錄開始行碼
*/
public static int getDataStartNum(int pageNum, int pageSize) {
return (pageNum - 1) * pageSize + 1;
}
/**
* 初始化分頁對象
*
* @param <T> 返回值類型
* @return 初始化分頁對象
*/
public static <T> PageEsData<T> newPageData() {
return new PageEsData<>(new ArrayList<>(), 0);
}
}
三、總結
1.存取方便,對象存,對象取;
轉載註明出處,看到缺點,請留言,謝謝先!