一、环境配置
版本在这里一定要注意,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;
}
以上是我总结的一些基本操作。