一、環境配置
版本在這裏一定要注意,es從6.3之後api發生了很多變化,很多api被棄用了。所以這裏用的是6.8.4.
導入jar包
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.8.4</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.8.4</version>
</dependency>
配置文件yml:
elasticsearch:
host: ip
port: port //這裏是9200端口對應rest請求
//這裏配置了low和high兩種
@Data
@Configuration
@ConfigurationProperties(prefix = "elasticsearch")
public class EsConfig{
private String host;
private Integer port;
@Bean(destroyMethod = "close")
public RestClient restClient() {
// 如果有多個從節點可以持續在內部new多個HttpHost,參數1是IP,參數2是端口,參數3是通信協議
RestClientBuilder clientBuilder = RestClient.builder(new HttpHost(host, port, "http"));
// 設置Header編碼
Header[] defaultHeaders = {new BasicHeader("content-type", "application/json")};
clientBuilder.setDefaultHeaders(defaultHeaders);
// 添加其他配置,這些配置都是可選的,詳情配置可看https://blog.csdn.net/jacksonary/article/details/82729556
return clientBuilder.build();
}
@Bean(destroyMethod = "close")
public RestHighLevelClient client() {
return new RestHighLevelClient(RestClient.builder(
new HttpHost(host, port, "http")
));
}
}
二、常見操作的API
1、添加索引,並創建mapping
這種操作常見於,es在直接向沒有設定mapping的索引中添加數據時,一些數據類型不能動態匹配比如,座標geo-point類型,ip類型等等,需要我們手動先創建好mapping,再進行數據添加操作。需要注意的是,新建索引要用CreateIndexRequest ,如果索引已經存在,則要用PutMappingRequest來進行修改了。
創建mapping時只需要創建特殊指定的字段就可以了。
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
@Service
@Slf4j
public class EsMappingCreateUtil {
@Autowired
private RestHighLevelClient highLevelClient;
public AcknowledgedResponse createStationMapping(String indexName){
//需要先創建索引
CreateIndexRequest request = new CreateIndexRequest(indexName);
String m= "{\n" +
" \"properties\": {" +
" \"location\": {" +
" \"type\": \"geo_point\"" +
" }," +
" \"baiduLocation\": {" +
" \"type\": \"geo_point\"" +
" }" +
" }" +
"}";
request.mapping(m, XContentType.JSON);
try {
//查詢索引是否存在,這裏索引名稱既可以是索引也可以是別名
GetIndexRequest getIndexRequest = new GetIndexRequest(indexName);
boolean exists = highLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
if(!exists){
AcknowledgedResponse getMappingResponse = highLevelClient.indices().create(request, RequestOptions.DEFAULT);
log.info("創建索引maping成功 {}",indexName);
return putMappingResponse;
}
log.info("索引{}已經存在",indexName);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
2、批量添加索引
此操作用於批量將數據添加進es索引庫中。切記數據中不能存在空的數據。否則添加失敗。
BulkRequest bulkRequest=new BulkRequest();
log.info("start={},endnow={}",start,endNow);
stationRepository.selectListByPage(start,endNow).forEach(station->{
JSONObject jsonObject=JSONObject.parseObject(station.getLocationStr());
station.setLocation(jsonObject);
JSONObject baiduLocation=JSONObject.parseObject(station.getBaiduLocationStr());
station.setBaiduLocation(baiduLocation);
bulkRequest.add(createIndexRequest(station,stationIndexName,EsConstant.STATION_TYPE,station.getStationId()), XContentType.JSON);
});
try {
BulkResponse bulkResponse=highLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);
log.info("索引{}批量添加結果bulkResponse={}",stationIndexName,JSONObject.toJSONString(bulkResponse));
} catch (IOException e) {
e.printStackTrace();
}
private IndexRequest createIndexRequest(final Object data, final String indexName, final String type, final String id) {
return new IndexRequest(indexName).id(id).type(type).source(beanToMap(data));
}
3、根據索引別名,查詢所有的索引名稱
此操作,通常會用於重建索引的時候,爲了查詢統一用別名來操作。會將每次新建的索引賦予一個統一的別名,但是之前的索引中的別名需要刪除,所以,需要根據別名先將索引名稱查詢出來進行刪除,添加和刪除操作見下一條。
但是這裏也有需要注意的地方,查詢如果是空的話,返回的結果並不是null,而是bytes或者empty,所以,我們在處理的時候也要注意。
/**
* 根據別名查詢所有的索引名稱
* @param aliasName 別名
* @return 索引名稱集合
*/
private Set<String> getIndexName(String aliasName){
Map<String,Object> resultMap=new HashMap<>();
try {
//先判斷別名是否存在
GetIndexRequest getIndexRequest = new GetIndexRequest(aliasName);
boolean exists = highLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
log.info("索引別名{}查詢是否存在{}",aliasName,exists);
if(exists){
Request request=new Request("GET","/_alias/"+aliasName);
Response response=highLevelClient.getLowLevelClient().performRequest(request);
if(response!=null){
resultMap=beanToMap(EntityUtils.toString(response.getEntity()));
}
return resultMap.keySet();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
4、索引別名添加和刪除
private void modifyAlias(String indexName,String alias,String method){
Map<String,Object> deleteAlias=new HashMap<>();
Map<String,String> methodMap=new HashMap<>();
methodMap.put("index",indexName);
methodMap.put("alias",alias);
deleteAlias.put(method,methodMap);
Object[] actions=new Object[1];
actions[0]=deleteAlias;
Map<String,Object> params=new HashMap<>();
params.put("actions",actions);
log.info("params={}",JSONObject.toJSONString(params));
try {
if("remove".equals(actions)){
GetIndexRequest getIndexRequest = new GetIndexRequest(alias);
boolean exists = highLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
log.info("刪除索引別名前查詢索引別名{}是否存在{}",alias,exists);
if(!exists){
return;
}
}
Request request=new Request("POST","/_aliases");
HttpEntity entity = new NStringEntity(JSONObject.toJSONString(params), ContentType.APPLICATION_JSON);
request.setEntity(entity);
Response response=highLevelClient.getLowLevelClient().performRequest(request);
log.info(JSONObject.toJSONString(response));
} catch (IOException e) {
e.printStackTrace();
}
}
//這裏是調用添加和刪除方法
private void addAliasName(String indexName,String aliasName){
Set<String> indexSet=getIndexName(aliasName);
if(indexSet!=null){
indexSet.forEach(index->{
//特殊處理一下查詢出來的結果
if(index!=null && !"bytes".equals(index) && !"empty".equals(index)){
modifyAlias(index,aliasName,"remove");
}
});
}
modifyAlias(indexName,aliasName,"add");
}
5、查詢
對於索引操作來說,查詢是最常見的操作了。所以這裏只舉個最常見的例子。
SearchRequest searchRequest=new SearchRequest(EsConstant.STATION_INDEX_NAME_ALIAS);
searchRequest.types(EsConstant.STATION_TYPE);
String searchKeyword="*"+keyword+"*";
searchRequest.source(buildKeywordSearchBuilder(searchKeyword));
try {
SearchResponse searchResponse=highLevelClient.search(searchRequest,RequestOptions.DEFAULT);
SearchHits searchHits=searchResponse.getHits();
List<Object> stationList=new ArrayList<>(20);
if(searchHits!=null && searchHits.getHits()!=null){
for(SearchHit hit:searchHits.getHits()){
OperatorStation station= JSONObject.parseObject(hit.getSourceAsString(),OperatorStation.class);
Map<String,Object> map=new HashMap<>(20);
map.put("id",station.getId());
stationList.add(map);
}
}
//構造查詢條件
SearchSourceBuilder buildKeywordSearchBuilder(String searchKeyword){
BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();
boolQueryBuilder.must(QueryBuilders.matchQuery("字段",條件))
.must(QueryBuilders.matchQuery("stationOnLine",條件))
.should(QueryBuilders.wildcardQuery("字段",searchKeyword))
.should(QueryBuilders.wildcardQuery("字段",searchKeyword));
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(boolQueryBuilder);
sourceBuilder.from(0);
sourceBuilder.size(15); //分頁
log.info("station-find-keyword query string ={}",sourceBuilder.toString());
return sourceBuilder;
}
以上是我總結的一些基本操作。