通过RestHighLevelClient实现ES聚合查询

功能简介

为了实现商品搜索时,动态展示分类筛选条件,需要借助聚合查询实现。

功能上有分页、搜索、字段聚合。

难点

做聚合查询时,商品都会有分类、品牌,可以直接使用agg函数查出,但商品的属性是动态变化的,需要进行多次聚合查询,将商品的属性转化为k-v形式(k-属性名,v-属性值集合)。特别是通过java取出时,也需要对数据进行进一步处理。

DSL语法

GET /goods/doc/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "brandName": {
              "value": "箭牌"
            }
          }
        },
        {
          "term": {
            "goodsCatId3Name.keyword": {
              "value": "合资品牌"
            }
          }
        }
      ],
      "filter": {
        "range": {
          "linePrice": {
            "gte": 10,
            "lte": 200
          }
        }
      }
    }
  },
  "size": 1,
  "aggs": {
    "brands": {
      "terms": {
        "field": "brandName"
      }
    },
    "categories3":{
      "terms": {
        "field": "goodsCatId3Name.keyword",
        "size": 10
      }
    },
    "searchList_agg":{
      "nested": {
        "path": "searchList"
      },
      "aggs": {
        "searchListName": {
          "terms": {
            "field": "searchList.name",
            "size": 10
          },
          "aggs": {
            "searchListNameValue": {
              "terms": {
                "field": "searchList.value",
                "size": 10
              }
            }
          }
        }
      }
    }
  }
}

响应结果:

"aggregations": {
    "brands": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "箭牌",
          "doc_count": 6
        }
      ]
    },
    "categories3": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "合资品牌",
          "doc_count": 6
        }
      ]
    },
    "searchList_agg": {
      "doc_count": 6,
      "searchListName": {
        "doc_count_error_upper_bound": 0,
        "sum_other_doc_count": 0,
        "buckets": [
          {
            "key": "合资品牌1",
            "doc_count": 6,
            "searchListNameValue": {
              "doc_count_error_upper_bound": 0,
              "sum_other_doc_count": 0,
              "buckets": [
                {
                  "key": "123",
                  "doc_count": 5
                },
                {
                  "key": "456",
                  "doc_count": 1
                }
              ]
            }
          }
        ]
      }
    }
  }

java客户端操作

代码片段

  Aggregations aggregations = searchResponse.getAggregations();
            //筛选条件
            List<Map> conditions = aggregations.asList().stream().map(GoodsIndexServiceImpl::apply).collect(Collectors.toList());
            map.put("conditions", conditions);
            log.info("conditions->"+conditions);

// 调用的静态方法
//aggregation convert
    private static Map apply(Aggregation aggregation) {
        Map map = new HashMap();
        if (aggregation instanceof ParsedStringTerms) {
            String name = aggregation.getName();
            List<ParsedStringTerms.ParsedBucket> collect = (List<ParsedStringTerms.ParsedBucket>) ((ParsedStringTerms) aggregation).getBuckets();
            List<String> stringList = collect.stream().map(a -> {
                String value = a.getKeyAsString() + "|" + a.getDocCount();
                return value;
            }).collect(Collectors.toList());
            map.put(name, stringList);
        }

        if (aggregation instanceof ParsedNested) {
            Aggregations aggregations = ((ParsedNested) aggregation).getAggregations();
            for (Aggregation aggregation1 : aggregations) {
                List<ParsedStringTerms.ParsedBucket> buckets = (List<ParsedStringTerms.ParsedBucket>) ((ParsedStringTerms) aggregation1).getBuckets();
                for (ParsedStringTerms.ParsedBucket bucket : buckets) {
                    //searchKey
                    String keyAsString = bucket.getKeyAsString();
                    Aggregations aggregations1 = bucket.getAggregations();
                    for (Aggregation aggregation2 : aggregations1) {
                        List<ParsedStringTerms.ParsedBucket> buckets1 = (List<ParsedStringTerms.ParsedBucket>) ((ParsedStringTerms) aggregation2).getBuckets();
                        //searchValueList
                        List<String> valueList = buckets1.stream().map(parsedBucket ->
                                parsedBucket.getKeyAsString() + "|" + parsedBucket.getDocCount()).collect(Collectors.toList());
                        map.put(keyAsString, valueList);
                    }
                }
            }
        }
        return map;
    }

处理后的返回值:
返回值
Json格式

[
    {
        "brands": [
            "箭牌|6",
            "3ce|2",
            "华为|1",
            "小米|1"
        ]
    },
    {
        "categories3": [
            "合资品牌|13"
        ]
    },
    {
        "合资品牌1": [
            "123|11",
            "456|1",
            "我去二|1"
        ],
        "合资品牌6": [
            "你好|1"
        ]
    }
]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值