|
|
package com.yoho.search.service.scene.ufo;
|
|
|
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.yoho.search.aop.cache.SearchCacheAble;
|
|
|
import com.yoho.search.base.utils.ISearchConstants;
|
|
|
import com.yoho.search.base.utils.SearchCollectionUtils;
|
|
|
import com.yoho.search.base.utils.UfoProductIndexEsField;
|
|
|
import com.yoho.search.common.SearchCommonService;
|
|
|
import com.yoho.search.common.utils.UfoImageUrlAssist;
|
|
|
import com.yoho.search.core.es.model.SearchParam;
|
|
|
import com.yoho.search.core.es.model.SearchResult;
|
|
|
import com.yoho.search.models.SearchApiResult;
|
|
|
import com.yoho.search.service.helper.UfoSearchQueryHelper;
|
|
|
import com.yoho.search.service.index.UfoBrandIndexBaseService;
|
|
|
import org.apache.commons.collections.MapUtils;
|
|
|
import org.elasticsearch.index.query.BoolQueryBuilder;
|
|
|
import org.elasticsearch.search.SearchHit;
|
|
|
import org.elasticsearch.search.SearchHits;
|
|
|
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
|
|
import org.elasticsearch.search.aggregations.Aggregation;
|
|
|
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
|
|
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation;
|
|
|
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
|
|
|
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
|
|
|
import org.elasticsearch.search.aggregations.metrics.tophits.TopHits;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import java.util.*;
|
|
|
|
|
|
/**
|
|
|
* @author wangnan
|
|
|
* @version 2018/12/13
|
|
|
*/
|
|
|
@Service
|
|
|
public class UfoSeriesListService {
|
|
|
|
|
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
|
|
private static final String firstAggName = "FirstAgg";
|
|
|
private static final String secondAggName = "SecondAgg";
|
|
|
|
|
|
@Autowired
|
|
|
private UfoSearchQueryHelper ufoSearchQueryHelper;
|
|
|
@Autowired
|
|
|
private SearchCommonService searchCommonService;
|
|
|
@Autowired
|
|
|
private UfoBrandIndexBaseService ufoBrandIndexBaseService;
|
|
|
|
|
|
@SearchCacheAble(cacheInMinute = 10, cacheName = "UFO_SERIES_LIST", excludeParams = {"order", "page", "viewNum"})
|
|
|
public SearchApiResult searchSeriesList(Map<String, String> paramMap) {
|
|
|
try {
|
|
|
SearchParam searchParam = new SearchParam();
|
|
|
searchParam.setSize(0);
|
|
|
//1.构造过滤
|
|
|
BoolQueryBuilder boolFilter = ufoSearchQueryHelper.constructFilterBuilder(paramMap, null);
|
|
|
searchParam.setFiter(boolFilter);
|
|
|
//2.构造聚合
|
|
|
List<AbstractAggregationBuilder<?>> list = new ArrayList<>();
|
|
|
// 2.1构造父聚合
|
|
|
TermsAggregationBuilder firstAggregationBuilder = AggregationBuilders.terms(firstAggName).field(UfoProductIndexEsField.brandId).order(Terms.Order.term(true)).size(1000);
|
|
|
// 2.2添加子聚合
|
|
|
TermsAggregationBuilder secondAggregationBuilder = AggregationBuilders.terms(secondAggName).field(UfoProductIndexEsField.seriesId).order(Terms.Order.term(true)).size(1000);
|
|
|
firstAggregationBuilder.subAggregation(secondAggregationBuilder);
|
|
|
// 2.3添加孙聚合
|
|
|
String[] includeField = SearchCollectionUtils.listToArray(Arrays.asList(UfoProductIndexEsField.brandId, UfoProductIndexEsField.seriesId, UfoProductIndexEsField.seriesName, UfoProductIndexEsField.defaultImages));
|
|
|
secondAggregationBuilder.subAggregation(AggregationBuilders.topHits("product").fetchSource(includeField, null).size(1));
|
|
|
list.add(firstAggregationBuilder);
|
|
|
searchParam.setAggregationBuilders(list);
|
|
|
//3.执行搜索
|
|
|
final String indexName = ISearchConstants.INDEX_NAME_UFO_PRODUCT_INDEX;
|
|
|
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
|
|
|
if (searchResult == null || searchResult.getAggMaps() == null) {
|
|
|
return new SearchApiResult().setData(null).setCode(500);
|
|
|
}
|
|
|
Map<String, Aggregation> aggregationResult = searchResult.getAggMaps();
|
|
|
if (!aggregationResult.containsKey(firstAggName)) {
|
|
|
return new SearchApiResult().setData(null).setCode(500);
|
|
|
}
|
|
|
//4.构造返回数据结构
|
|
|
List<Map<String, Object>> seriesList = this.getSeriesList(aggregationResult);
|
|
|
JSONObject jsonObject = new JSONObject();
|
|
|
jsonObject.put("series_list", seriesList);
|
|
|
jsonObject.put("total", seriesList.size());
|
|
|
return new SearchApiResult().setData(jsonObject);
|
|
|
} catch (Exception e) {
|
|
|
logger.error(e.getMessage(), e);
|
|
|
return new SearchApiResult().setData(null).setCode(500);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private List<Map<String, Object>> getSeriesList(Map<String, Aggregation> aggregationResult) {
|
|
|
List<Map<String, Object>> returnList = new ArrayList<>();
|
|
|
//brand层聚合
|
|
|
MultiBucketsAggregation brandIdAgg = ((MultiBucketsAggregation) aggregationResult.get(firstAggName));
|
|
|
//获取brandId->brandLogo映射
|
|
|
Map<String, String> brandLogoMap = this.buildBrandLogoMap(brandIdAgg);
|
|
|
for (MultiBucketsAggregation.Bucket brandIdBucket : brandIdAgg.getBuckets()) {
|
|
|
String brandId = brandIdBucket.getKeyAsString();
|
|
|
JSONArray seriesArray = new JSONArray();
|
|
|
//series层聚合
|
|
|
MultiBucketsAggregation seriesIdAgg = (MultiBucketsAggregation) brandIdBucket.getAggregations().asMap().get(secondAggName);
|
|
|
for (MultiBucketsAggregation.Bucket shopIdBucket : seriesIdAgg.getBuckets()) {
|
|
|
if (!shopIdBucket.getAggregations().getAsMap().containsKey("product")) {
|
|
|
continue;
|
|
|
}
|
|
|
//series下面取一个product
|
|
|
TopHits topHits = shopIdBucket.getAggregations().get("product");
|
|
|
Map<String, Object> source = getTopHitResult(topHits);
|
|
|
seriesArray.add(this.buildSeriesReturnObject(source));
|
|
|
}
|
|
|
Map<String, Object> brandMap = this.buildBrandReturnMap(brandId, brandLogoMap.get(brandId), seriesArray);
|
|
|
returnList.add(brandMap);
|
|
|
}
|
|
|
return returnList;
|
|
|
}
|
|
|
|
|
|
private Map<String, String> buildBrandLogoMap(MultiBucketsAggregation brandIdAgg) {
|
|
|
Set<String> brandIdSet = new HashSet<>();
|
|
|
for (MultiBucketsAggregation.Bucket brandIdBucket : brandIdAgg.getBuckets()) {
|
|
|
brandIdSet.add(brandIdBucket.getKeyAsString());
|
|
|
}
|
|
|
return ufoBrandIndexBaseService.getBrandLogoMapByIds(brandIdSet);
|
|
|
}
|
|
|
|
|
|
private Map<String, Object> buildBrandReturnMap(String brandId, String brandLogo, JSONArray seriesArray) {
|
|
|
Map<String, Object> brandMap = new LinkedHashMap<>();
|
|
|
brandMap.put("brand_id", brandId);
|
|
|
brandMap.put("brand_logo", UfoImageUrlAssist.getAllProductPicUrl(brandLogo, "brandLogo", "center", "d2hpdGU="));
|
|
|
brandMap.put("brand_series", seriesArray);
|
|
|
return brandMap;
|
|
|
}
|
|
|
|
|
|
private JSONObject buildSeriesReturnObject(Map<String, Object> source) {
|
|
|
JSONObject jsonObject = new JSONObject();
|
|
|
jsonObject.put("series_id", MapUtils.getString(source, UfoProductIndexEsField.seriesId, ""));
|
|
|
jsonObject.put("series_name", MapUtils.getString(source, UfoProductIndexEsField.seriesName, ""));
|
|
|
String seriesImage = MapUtils.getString(source, UfoProductIndexEsField.defaultImages, "");
|
|
|
jsonObject.put("series_image", UfoImageUrlAssist.getAllProductPicUrl(seriesImage, "goodsimg", "center", "d2hpdGU="));
|
|
|
return jsonObject;
|
|
|
}
|
|
|
|
|
|
private Map<String, Object> getTopHitResult(TopHits topHits) {
|
|
|
if (topHits == null) {
|
|
|
return null;
|
|
|
}
|
|
|
SearchHits hits = topHits.getHits();
|
|
|
if (hits.getHits() == null || hits.getHits().length == 0) {
|
|
|
return null;
|
|
|
}
|
|
|
SearchHit hit = hits.getHits()[0];
|
|
|
return hit.getSource();
|
|
|
}
|
|
|
|
|
|
} |
...
|
...
|
|