項目中要對es中的商品聚合出 前端一級分類與二級分類,並且對一二級分類按設置的排序值進行排序後返回樹型結構;
項目中一個商品可以對應多個前臺分類 , 所以es索引中前臺分類用Nested類型存儲,_mapping結構如下:
存儲數據時對 一二三級分類數據的相關字段拼接成 id|name|parentId|sort|level|icon 這樣的字符串;
java代碼如下:
代碼中:EsProductFields.frontFirstCategoryInfo="frontCategoryList.frontFirstCategoryInfo.keyword"
EsProductFields.frontSecondCategoryInfo="frontCategoryList.frontSecondCategoryInfo.keyword"
@Autowired
private ElasticsearchRestTemplate es;
public List<ESCategoryDTO> selectCategoryList(SearchParameter param) {
NativeSearchQueryBuilder queryBuilder = getSearchQuery(param);
queryBuilder.withFilter(queryMustFilter(getFilter(param)));
queryBuilder.withPageable(PageRequest.of(0, 1));
//聚合一級分類
TermsAggregationBuilder firstTermsAgg = AggregationBuilders.terms(EsProductFields.frontFirstCategoryInfo).field(EsProductFields.frontFirstCategoryInfo);
firstTermsAgg.size(200);
queryBuilder.addAggregation(firstTermsAgg);
//聚合二級分類
TermsAggregationBuilder secondTermsAgg = AggregationBuilders.terms(EsProductFields.frontSecondCategoryInfo).field(EsProductFields.frontSecondCategoryInfo);
secondTermsAgg.size(10000);
queryBuilder.addAggregation(secondTermsAgg);
List<ESCategoryDTO> categoryList = new ArrayList<>();
List<String> list = new ArrayList<>();
SearchHits<EsProductDTO> search = es.search(queryBuilder.build(), EsProductDTO.class);
if (search.hasSearchHits()) {
for (Aggregation item : search.getAggregations()) {
JSONObject jsonObject = JSONUtil.parseObj(item);
//取出聚合結果桶裏的數據
JSONArray buckets = jsonObject.getJSONArray("buckets");
for (Object bucket : buckets) {
JSONObject model = JSONUtil.parseObj(bucket);
list.add(model.get("key").toString());
}
}
}
if (CollUtil.isNotEmpty(list)) {
for (String item : list) {
//id|name|parentId|sort|level|icon 分類信息按豎線分割
String[] categoryArr = item.split("\\|");
ESCategoryDTO model = new ESCategoryDTO();
model.setId(categoryArr[0]);
model.setName(categoryArr[1]);
model.setParentId(Long.parseLong(categoryArr[2]));
model.setSort(Integer.parseInt(categoryArr[3]));
model.setLevel(Integer.parseInt(categoryArr[4]));
model.setIcon(categoryArr[5].equals("null") ? "" : categoryArr[5]);
categoryList.add(model);
}
}
if (CollUtil.isNotEmpty(categoryList)) {
//組裝成樹型結構
List<ESCategoryDTO> firstCategoryList = categoryList.stream().filter(c -> c.getLevel().equals(CategoryLevel.FIRST)).collect(Collectors.toList());
//一級分類按sort排序
firstCategoryList.sort(Comparator.comparing(ESCategoryDTO::getSort).reversed());
for (ESCategoryDTO item : firstCategoryList) {
List<ESCategoryDTO> secondCategoryList = categoryList.stream().filter(c -> c.getParentId().equals(Long.parseLong(item.getId()))).collect(Collectors.toList());
//二級分類按sort排序
secondCategoryList.sort(Comparator.comparing(ESCategoryDTO::getSort).reversed());
item.setChildCategoryList(secondCategoryList);
}
return firstCategoryList;
}
return new ArrayList<>();
}