1. 程式人生 > >elasticsearch查詢多欄位聚合

elasticsearch查詢多欄位聚合

1,需求:

在分頁查詢的同時,返回所查詢商品的類目和品牌的聚合資訊

2,mapping:
    {
        "item" : {
            "properties" : {
                "item_name" : {
                    "type" : "string",
                                        "index" : "analyzed",
                                        "analyzer" : "ik_smart"
                },
               "brand_name" : {
                    "type" : "multi_field",
                    "fields" : {
                        "brand_name" : {"type" : "string", "index" : "analyzed", "analyzer" :"ik_smart"},
                        "brand_name_agg" : {"type" : "string", "index" : "not_analyzed"}
                    }
                },
                "c_name" : {
                    "type" : "multi_field",
                    "fields" : {
                        "c_name" : {"type" : "string", "index" : "analyzed","analyzer" :"ik_smart"},
                        "c_name_agg" : {"type" : "string", "index" : "not_analyzed"}
                    }
                }
            }
        }
    }

這裡需要注意的是brand_name如果設定為ik分詞,聚合結果也會進行分詞,導致結果不準確

可對brand_name進行multi_field設定,query時使用brand_name,agg時使用brand_name_agg

3,查詢時需要注意如果分別統計兩個不相關的欄位,可設定aggregations下多個結果集,若統計有父子關係的欄位,

例如某年級下某班級的學生個數,可使用subAggregation功能

search:

 {"from" : 0,
  "size" : 20,
  "query" : {
    "bool" : {
      "must" : {
        "fuzzy" : {
          "item_name" : {
            "value" : "西門子"
          }
        }
      }
    }
  },
  "explain" : true,
  "aggregations" : {
    "brand_name.brand_name_agg" : {
      "terms" : {
        "field" : "brand_name.brand_name_agg",
        "size" : 9999,
        "order" : {
          "_count" : "asc"
        }
      }
    },
    "c_name.c_name_agg" : {
      "terms" : {
        "field" : "c_name.c_name_agg",
        "size" : 9999,
        "order" : {
          "_count" : "asc"
        }
      }
    }
  }
}

4,相關java實現方式:

1)查詢條件構建:

SearchRequestBuilder builder = client.prepareSearch(index).setTypes(type);
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
TermsBuilder termsBuilder = AggregationBuilders.terms(aggregation.getField());
termsBuilder.field(aggregation.getField());
if(SortConstant.SortASC
.equals(aggregation.getOrder())){ termsBuilder.order(Terms.Order.aggregation("_count", true)); }else{ termsBuilder.order(Terms.Order.aggregation("_count", false)); } termsBuilder.size(aggregation.getSize()); builder.addAggregation(termsBuilder); 2)查詢結果返回:
Map<String,List<Object>> aggrMap = new HashMap<String, List<Object>>();
List<Aggregation> aggregationList = searchCondition.getAggregationList();
if(aggregationList!=null && aggregationList.size() > 0){
    for(Aggregation aggregation : aggregationList){
        List<Object> results = new ArrayList<Object>();
        Terms result = searchResponse.getAggregations().get(aggregation.getField());
        for (Terms.Bucket entry : result.getBuckets()) {
            results.add(entry.getKey());
        }
        aggrMap.put(aggregation.getField(),results);
    }
}

5,參考資料:
http://www.cnblogs.com/xing901022/p/4947436.html?utm_source=tuicool&utm_medium=referral
http://blog.csdn.net/xiaohelong2005/article/details/41513985
http://www.cnblogs.com/sha0830/p/5549331.html