版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/heihu_malice7/article/details/83897815
工作中使用到elasticsearch,整理了一下常用的api示例,仅供参考!!!
package com.jd.jr.poi.utils;
import com.jd.jr.poi.constant.Constants;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.*;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.metrics.avg.Avg;
import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import java.math.BigDecimal;
import java.util.*;
/**
* BoolQuery:进行搜索的代码,适用于复杂搜索逻辑
* must:文档必须完全匹配条件
* mustNot:文档必须不匹配条件
* should:should下面会带一个以上的条件,至少满足一个条件,这个文档就符合should
* termQuery:完全匹配
* termsQuery:一次匹配多个值
* matchQuery:单个匹配, field不支持通配符, 前缀具高级特性
* matchPhraseQuery 必须所有term都在doc field中出现,而且距离在slop限定范围内才能匹配上,可指定slot值,默认设置每个分词之间的间隔为0
* multiMatchQuery:匹配多个字段, field有通配符忒行
* matchAllQuery:匹配所有文件
* filter:过滤出想要的文件,不是过滤掉文件
*/
public class EsUtil implements Constants {
/**
* 正则过滤文件
* @param esClient
* @param index
* @param type
*/
public void regex(Client esClient,String index,String type){
QueryBuilder qb2 = QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("city","北京")).mustNot(QueryBuilders.regexpQuery("district", ".*(海|淀).*"));
SearchResponse searchResponse =esClient.prepareSearch(index).setQuery(qb2).execute().actionGet();
LoggerUtil.info("regex-response:{}", JsonUtil.toJSON(searchResponse));
}
/**
* 获取平均值
* @param esClient
* @param index
* @param type
* @param qb 条件
* @param field 对应的属性字段
*/
public void getAvgPr(Client esClient,String index,String type,QueryBuilder qb, String field){
AggregationBuilder termsBuilder = AggregationBuilders.avg("avg").field(field);
SearchRequestBuilder sv=esClient.prepareSearch(index).setTypes(type).setQuery(qb).addAggregation(termsBuilder);
SearchResponse response= sv.execute().actionGet();
Avg valueCount= response.getAggregations().get("avg");
int intVal = ParserUtil.douToInt(valueCount.getValue(),0, BigDecimal.ROUND_UP);
LoggerUtil.info("平均值,value:{}",intVal);
}
/**
* 查询坐标1到坐标2矩形范围内,的用户有那些
*/
public void testGetNearbyPeople(Client esClient,String index,String type, double lat1, double lon1, double lat2,double lon2) {
SearchRequestBuilder srb = esClient.prepareSearch(index).setTypes(type);
SearchResponse searchResponse = srb.setQuery(QueryBuilders.geoBoundingBoxQuery("location").setCorners(lat1, lon1, lat2, lon2)).get();
for (SearchHit searchHit : searchResponse.getHits().getHits()) {
LoggerUtil.info("getJuxing-response:{}", JsonUtil.toJSON(searchHit.getSourceAsString()));
}
}
/**
* 是否存在
* @param esClient
* @param index
* @param type
*/
public void isHaving(Client esClient,String index,String type){
//组装ES查询条件
QueryBuilder qb =qb = QueryBuilders.boolQuery().must(QueryBuilders.matchPhraseQuery("id","0185d356e02d4214e82888b"));
//search_type设置为query_and_fetch的聚合查询不会导致内存溢出,而默认的query_then_fetch则会内存溢出
SearchResponse poiResponse=esClient.prepareSearch(index).setTypes(type).setQuery(qb).setSearchType(SearchType.QUERY_AND_FETCH).execute().actionGet();
LoggerUtil.info("poiResponse1:{}",JsonUtil.toJSON(poiResponse));
}
/**
* 获取坐标 附近1000米的信息
*
*/
public void getNearbyPosition(Client esClient,String index,String type) {
SearchRequestBuilder srb = esClient.prepareSearch(index).setTypes(type);
srb.setFrom(0).setSize(1000);// 1000人
GeoDistanceQueryBuilder location1 = QueryBuilders.geoDistanceQuery("location").point(40.372486, 40.372486).distance(5000, DistanceUnit.MILES);
srb.setPostFilter(location1);
// 获取距离多少公里 这个才是获取点与点之间的距离的
GeoDistanceSortBuilder sort = SortBuilders.geoDistanceSort("location", 40.372486, 40.372486);
sort.unit(DistanceUnit.MILES);
sort.order(SortOrder.ASC);
sort.point(40.372486, 40.372486);
srb.addSort(sort);
SearchResponse searchResponse = srb.execute().actionGet();
LoggerUtil.info("getNearbyPosition-response:{}",JsonUtil.toJSON(searchResponse));
SearchHits hits = searchResponse.getHits();
SearchHit[] searchHists = hits.getHits();
// 搜索耗时
Float usetime = searchResponse.getTookInMillis() / 1000f;
LoggerUtil.info("getNearbyPosition-response:{}","坐标附近有(" + hits.getTotalHits() + "个),耗时(" + usetime + "秒):");
for (SearchHit hit : searchHists) {
String name = (String) hit.getSource().get("district");
GeoPointLL location_ = JsonUtil.toBean(JsonUtil.toJSON(hit.getSource().get("location")),GeoPointLL.class);
// 获取距离值,并保留两位小数点
BigDecimal geoDis = new BigDecimal((Double) hit.getSortValues()[0]);
Map<String, Object> hitMap = hit.getSource();
// 在创建MAPPING的时候,属性名的不可为geoDistance。
hitMap.put("geoDistance", geoDis.setScale(0, BigDecimal.ROUND_HALF_DOWN));
LoggerUtil.info("getNearbyPosition-location:{}",name + "的坐标:" + JsonUtil.toJSON(location_) + "距离坐标" + hit.getSource().get("geoDistance") + DistanceUnit.METERS.toString());
}
}
/**
* 地理位置
* 不用org.elasticsearch.common.geo.GeoPoint,会抛org.elasticsearch.ElasticsearchParseException:field必须是lat / lon或geohash
*/
class GeoPointLL {
double lat, lon;
public GeoPointLL() {
}
public GeoPointLL(double lat, double lon) {
this.lat = lat;
this.lon = lon;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getLon() {
return lon;
}
public void setLon(double lon) {
this.lon = lon;
}
}
/**
* 多边形查询
*/
public void polygonQuery(Client esClient,String index,String type) {
List<GeoPoint> points=new ArrayList<GeoPoint>();
points.add(new GeoPoint(42, -72));
points.add(new GeoPoint(39, 117));
points.add(new GeoPoint(40, 117));
SearchResponse response = esClient.prepareSearch(index).setTypes(type).setQuery(QueryBuilders.geoPolygonQuery("location",points)).get();
LoggerUtil.info("polygonQuery:{}",JsonUtil.toJSON(response));
}
/**
* 写入
* @param esClient
* @param index
* @param type
* @param map 写入数据
*/
public void writeES(Client esClient,String index,String type,Map<String, Object> map){
LoggerUtil.info("prepareIndex-request:{}",JsonUtil.toJSON(map));
IndexResponse response = esClient.prepareIndex(index, type).setSource(map).get();
LoggerUtil.info("prepareIndex-response:{}",JsonUtil.toJSON(response));
}
/**
* 更新
* @param esClient
* @param index
* @param type
* @param id 当前数据的id主键,searchHit.getId()
*/
private void upSetES(Client esClient, String index, String type, String id){
try {
UpdateRequest updateRequest = new UpdateRequest(index, type, id);
updateRequest.doc(XContentFactory.jsonBuilder().startObject()
.field("name", "Joe Smith")
.endObject());
esClient.update(updateRequest).actionGet();
}catch (Exception e){
LoggerUtil.error("upSetES,调用失败", e.getMessage(), e);
}
}
/**
* 分页获取
* @param esClient
* @param index
* @param type
* @throws Exception
*/
private void getDataByPage(Client esClient, String index, String type){
//初始化对象
SearchHits hits = null;SearchHit[] hitArray = null;
try {
//组装ES查询条件
QueryBuilder qb = QueryBuilders.boolQuery().must(QueryBuilders.matchPhraseQuery("name","Joe Smith"));
/**
* 查询建立
* setSearchType, 执行检索的类别
* setSize,需要查询出多少条结果;
* setFrom,从哪一个Score开始查;
* 注:from*size要小于10000
* addSort,设置排序;
* setScroll,设置滚动的时间;
*/
SearchResponse poiResponse=esClient.prepareSearch(esIndexName).setTypes(esTypeName)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setScroll(TimeValue.timeValueMinutes(1))
.setQuery(qb)
.setSize(esPageNum).execute().actionGet();
while (true) {
hits = poiResponse.getHits();
hitArray = hits.getHits();
for (SearchHit searchHit : hitArray) {
LoggerUtil.info("getDataByPage-id:{}",searchHit.getId());
}
poiResponse = esClient.prepareSearchScroll(poiResponse.getScrollId()).setScroll(TimeValue.timeValueMinutes(10)).execute().actionGet();
if (poiResponse.getHits().getHits().length == 0) {
break;
}
//初始化对象
hits=null;hitArray=null;
}
/**
* 处理结束后,记得clean scroll,清除滚动ID
*/
clearScroll(esClient,poiResponse.getScrollId());
//初始化对象
qb=null;poiResponse=null;
} catch (Exception e) {
LoggerUtil.error("getDataByPage-getPoiData,获取POI数据失败", e.getMessage(), e);
}
}
/**
* 清除滚动ID
* 虽然当滚动有效时间已过,搜索上下文(Search Context)会自动被清除,但是一值保持滚动代价也是很大的,所以当我们不在使用滚动时要尽快使用Clear-Scroll API进行清除。
* @param scrollId
* @return
*/
public boolean clearScroll(Client esClient,String scrollId){
ClearScrollRequestBuilder clearScrollRequestBuilder = esClient.prepareClearScroll();
clearScrollRequestBuilder.addScrollId(scrollId);
ClearScrollResponse response = clearScrollRequestBuilder.get();
LoggerUtil.info("clearScroll,处理结束后,清除滚动ID,result;{}",JsonUtil.toJSON(response));
return response.isSucceeded();
}
}