1. 程式人生 > >Elasticsearch 多欄位聚合 結果封裝為map

Elasticsearch 多欄位聚合 結果封裝為map

開發十年,就只剩下這套架構體系了! >>>   

elasticsearch版本:6.1.1
資料欄位:

    id    aac003    yka055    id_drg    name_drg    id_mdc    name_mdc    id_depa

索引建立:

    

//todo 建立索引
    private void createIndex(TransportClient client)throws Exception{
        CreateIndexRequestBuilder cib=client.admin().indices().prepareCreate("hisms_sz");

        // 設定該index的Mapping,可暫時不設定,後面建完index之後再設定也可
        cib.addMapping("cz", createMapping());
        // 設定該index的Settings配置,常用的有shard數量、副本數
        cib.setSettings(createSetting());
        cib.execute().get();
        System.out.println("----------新增對映成功----------");
    }
    /**
     * 建立索引--id	aac003	yka055	id_drg	name_drg	id_mdc	name_mdc	id_depa
     */
    private XContentBuilder createMapping() throws IOException {
        XContentBuilder mapping = XContentFactory.jsonBuilder()
                .startObject()

                    .startObject("properties") //設定之定義欄位

                        .startObject("aac003")
                            .field("type","keyword") //設定資料型別
                        .endObject()
                        .startObject("yka055")
                            .field("type","double")
                        .endObject()
                        .startObject("name_drg")
                        .field("type","keyword")
                        .endObject()
                        .startObject("id_mdc")
                        .field("type","keyword")
                        .endObject()
                        .startObject("name_mdc")
                        .field("type","keyword")
                        .endObject()
                        .startObject("id_drg")
                            .field("type","text")
                            .startObject("fields")
                                .startObject("id_drg_key")
                                    .field("type","keyword")
                                .endObject()
                            .endObject()
                        .endObject()

                        .startObject("id_depa")
                            .field("type","text")
                            .startObject("fields")
                                .startObject("id_depa_key")
                                    .field("type","keyword")
                                 .endObject()
                            .endObject()
                        .endObject()

                        .startObject("date")
                            .field("type","date")  //設定Date型別
                            .field("format","yyyy-MM-dd HH:mm:ss")//設定Date的格式
                        .endObject()
                    .endObject()
                .endObject();
        return mapping;


    }

聚合查詢:

    

private void getAggsResult(TransportClient client){
        SearchResponse agg = client.prepareSearch("hisms_sz")
                .setTypes("cz")
                .addAggregation(
                        AggregationBuilders.terms("id_mdc").field("id_mdc").size(26)//設定聚合條件 group by id_mdc,id_drg
                                .subAggregation(
                                        AggregationBuilders.terms("name_drg").field("name_drg").size(700)
                                                .subAggregation(AggregationBuilders.avg("avg").field("yka055"))// 聚合結果 avg(date
                                                .subAggregation(AggregationBuilders.sum("sum").field("yka055"))
                                                .subAggregation(AggregationBuilders.min("min").field("yka055"))
                                                .subAggregation(AggregationBuilders.count("count").field("aac003"))
                                                .subAggregation(AggregationBuilders.cardinality("cardinality").field("aac003"))
                                )
                )
                .execute().actionGet();
        ArrayList<Object> results = results(agg);
        System.out.println(results.size());


    }

呼叫封裝方法:

    

private ArrayList<Object> results(SearchResponse agg){
        Map<String, Aggregation> aggregations = agg.getAggregations().asMap();


        ArrayList<Object> objects = new ArrayList<>();
        for (Map.Entry<String, Aggregation> entry:aggregations.entrySet()
        ) {

            String key = entry.getKey();
            Aggregation value = entry.getValue();
            HashMap<String, Object> group = new HashMap<>();
            parseAggs(value,group,key,objects);
        }
        return objects;
    }



    //解析聚合結果
    private ArrayList<Object> parseAggs(Aggregation agg, HashMap<String, Object> group,String field,ArrayList<Object> objects){

        if (agg instanceof Terms){
            for (Terms.Bucket bucket:((Terms) agg).getBuckets() ){

                String keyAsString = bucket.getKeyAsString();
                group.put(field,keyAsString);

                for (Map.Entry<String, Aggregation> entry :bucket.getAggregations().asMap().entrySet()
                     ) {
                    String key = entry.getKey();
                    Aggregation value = entry.getValue();

                    if (value instanceof Terms){
                        parseAggs(value,group,key,objects);
                    }else {
                        LinkedHashMap<String, Object> map = package2map(bucket);
                        map.putAll(group);
                        objects.add(map);
                        break;
                    }
                }
            }
        }

        return objects;

    }


    private  LinkedHashMap<String, Object> package2map(Terms.Bucket bucket){
        LinkedHashMap<String, Object> map = new LinkedHashMap<>();

        for (Map.Entry<String, Aggregation> entry :bucket.getAggregations().asMap().entrySet()
        ) {
            String key = entry.getKey();
            Aggregation value = entry.getValue();
            map.put(key,getvalue(value));
        }
        return map;
    }


    //取值
    public String getvalue(Aggregation agg){
        String type = agg.getType();


        String result="";
        switch (type){
            case "avg":
                result=String.valueOf(((InternalAvg) agg).getValue());
                break;
            case "sum":
                result=String.valueOf(((Sum) agg).getValue());
                break;
            case "value_count":
                result=String.valueOf(((InternalValueCount) agg).getValue());
                break;
            case "min":
                result=String.valueOf(((InternalMin) agg).getValue());
                break;
            case "max":
                result=String.valueOf(((InternalMax) agg).getValue());
                break;
            case "cardinality":
                result=String.valueOf(((InternalCardinality) agg).getValue());
                break;
            default:
                result=String.valueOf(agg);
                break;

        }
        return result;
    }

封裝後結果為List<Map>,同sql資料庫中查詢的一樣,方便遍歷查詢,不用再迴圈遍歷取