elasticsearch api示例

版权声明:本文为博主原创文章,未经博主允许不得转载。 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();
    }
}

猜你喜欢

转载自blog.csdn.net/heihu_malice7/article/details/83897815