elasticsearch api示例
阿新 • • 發佈:2018-12-21
工作中使用到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(); } }