Authored by 胡古飞

优化活动聚合逻辑

... ... @@ -85,21 +85,43 @@ public class AggProductListServiceImpl implements IAggProductListService, Applic
aggTypeToEsField.put("sort", "smallSortId");
aggTypeToEsField.put("brand", "brandId");
}
private QueryBuilder builderActivityQueryBuilder(Map<String, String> paramMap) {
// FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(QueryBuilders.matchAllQuery());
// functionScoreSearchHelper.addActivityPersonalizedScriptScore(functionScoreQueryBuilder, paramMap);
// return functionScoreQueryBuilder;
return searchServiceHelper.constructQueryBuilderForProductList(paramMap);
}
/**
* 获取每个桶的商品数量
*
* @param paramMap
* @return
*/
private int getTopHitsSize(Map<String, String> paramMap) {
int topHitsSize = 1;
try {
topHitsSize = Integer.valueOf(paramMap.get("aggTypeSize"));
} catch (Exception e) {
}
if (topHitsSize <= 0) {
topHitsSize = 1;
}
return topHitsSize;
}
/**
* @aggType=brand[聚合类型]
* @brand=1,2,3,4,5,6,7,8,9,10[聚合的值]
* @viewNum=10[总数]
* @aggTypeSize=1|2|3[每种品牌最多的个数]
* @second_order=shelve_time:desc[次要排序条件]
*/
@Override
public SearchApiResult aggProductList(Map<String, String> paramMap) {
try {
logger.info("[func=aggProductList][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、参数校验
String aggType = paramMap.get("aggType");
String aggType = paramMap.get("aggType");// 获取聚合类型
if (StringUtils.isBlank(aggType) || !aggTypeToEsField.containsKey(aggType)) {
return new SearchApiResult().setCode(400).setData("聚合类型非法");
}
... ... @@ -107,28 +129,36 @@ public class AggProductListServiceImpl implements IAggProductListService, Applic
return new SearchApiResult().setCode(400).setData("请传对应聚合类型的参数");
}
// 2、构造核心参数
String[] values = paramMap.get(aggType).split(",");
int viewNum = (values == null ? 10 : values.length);
String firstAggFiled = aggTypeToEsField.get(aggType);
// 3、构造查询条件
// 2、构造查询条件
SearchParam searchParam = new SearchParam();
//paramMap.put("promotion", null);
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));//活动特定的个性化
searchParam.setQuery(this.builderActivityQueryBuilder(paramMap));
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
searchParam.setQuery(this.builderActivityQueryBuilder(paramMap));// 活动特定的个性化
searchParam.setSize(0);
// 3、构造核心参数
String[] aggTypeValues = paramMap.get(aggType).split(",");// 获取聚合类型的值
int aggTypeValueSize = (aggTypeValues == null ? 10 : aggTypeValues.length);// 获取聚合的桶大小
int topHitsSizeSize = this.getTopHitsSize(paramMap);
String firstAggField = aggTypeToEsField.get(aggType);
// 4、构造聚合条件
final String firstAggName = "firstAgg";
String order = "sales_num:desc";
if (searchCommonHelper.isNeedPersonalSearch(paramMap)) {
order = "_score:desc";
}
order = searchSortHelper.dealSortField(order, false);
String sortField = order.split(":")[0];
SortOrder sortOrder = order.split(":")[1].equals("desc") ? SortOrder.DESC : SortOrder.ASC;
List<AbstractAggregationBuilder> list = new ArrayList<AbstractAggregationBuilder>();
// 4.1)构造父聚合:品牌或品类聚合【同时按子聚合的sort字段排序】
TermsBuilder brandAggregationBuilder = AggregationBuilders.terms(firstAggName).field(firstAggFiled).order(Terms.Order.aggregation("sort", false)).size(viewNum);
TermsBuilder brandAggregationBuilder = AggregationBuilders.terms(firstAggName).field(firstAggField).order(Terms.Order.aggregation("sort", false))
.size(aggTypeValueSize);
// 4.2)添加子聚合:取得分最大的值
brandAggregationBuilder.subAggregation(AggregationBuilders.max("sort").field("_score"));
brandAggregationBuilder.subAggregation(AggregationBuilders.max("sort").field(sortField));
// 4.3)添加孙聚合:取打分最高的一个product
brandAggregationBuilder.subAggregation(AggregationBuilders.topHits("product").addSort(SortBuilders.fieldSort("_score").order(SortOrder.DESC)).setSize(1));
brandAggregationBuilder.subAggregation(AggregationBuilders.topHits("product").addSort(SortBuilders.fieldSort(sortField).order(sortOrder)).setSize(topHitsSizeSize));
list.add(brandAggregationBuilder);
searchParam.setAggregationBuilders(list);
... ... @@ -150,7 +180,17 @@ public class AggProductListServiceImpl implements IAggProductListService, Applic
if (!aggMaps.containsKey(firstAggName)) {
return searchApiResult.setData("");
}
List<Map<String, Object>> productList = this.getProductList(((MultiBucketsAggregation) aggMaps.get(firstAggName)));
// 8、获取聚合结果
// 8.1)获取总的条数,没传则取aggTypeValueSize*topHitsSizeSize
int viewNum = StringUtils.isBlank(paramMap.get("viewNum")) ? aggTypeValueSize * topHitsSizeSize : Integer.parseInt(paramMap.get("viewNum"));
// 8.2)获取次要排序条件,并按次要排序条件重排
String second_order = paramMap.get("second_order");
if (StringUtils.isBlank(second_order)) {
second_order = "first_shelve_time:desc";
}
second_order = searchSortHelper.dealSortField(second_order, false);
List<Map<String, Object>> productList = this.getAggProductListResult(((MultiBucketsAggregation) aggMaps.get(firstAggName)), viewNum, order, second_order);
jsonObject = new JSONObject();
jsonObject.put("total", productList == null ? 0 : productList.size());
jsonObject.put("page", 1);
... ... @@ -166,36 +206,21 @@ public class AggProductListServiceImpl implements IAggProductListService, Applic
}
}
private List<Map<String, Object>> getProductList(final MultiBucketsAggregation aggregation) {
Iterator<? extends Bucket> itAgg = aggregation.getBuckets().iterator();
// 获取品牌聚合出来的商品
TopHits topHits;
SearchHits hits;
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
List<Map<String, Object>> dataList = new ArrayList<Map<String, Object>>();
List<String> sknStr = new ArrayList<String>();
while (itAgg.hasNext()) {
Bucket lt = itAgg.next();
if (lt.getAggregations().getAsMap().containsKey("product")) {
topHits = lt.getAggregations().get("product");
if (topHits != null) {
hits = topHits.getHits();
for (SearchHit hit : hits.getHits()) {
sknStr.add("" + hit.getSource().get("productSkn"));
dataList.add(hit.getSource());
}
}
}
}
try {
Map<String, List<Map<String, Object>>> productPricePlanMap = searchServiceHelper.searchProductPricePlan((String[]) sknStr.toArray(new String[sknStr.size()]));
for (Map<String, Object> m : dataList) {
result.add(searchServiceHelper.getProductMapWithPricePlan(m, productPricePlanMap));
}
} catch (Exception e) {
logger.error("[func=aggProductList][Exception={}][begin={}]", e, System.currentTimeMillis());
}
return result;
private List<Map<String, Object>> getAggProductListResult(final MultiBucketsAggregation aggregation, int viewNum, String order, String second_order) {
// 1、从聚合结果中获取原生数据
List<Map<String, Object>> productList = this.getProductListWithFromAggregation(aggregation);
String sortField = null;
SortOrder sortOrder = null;
// 2、按指定的首要规则排序
sortField = order.split(":")[0];
sortOrder = order.split(":")[1].equals("desc") ? SortOrder.DESC : SortOrder.ASC;
productList = this.sortListBySortField(productList, Integer.MAX_VALUE, sortField, sortOrder);
// 3、按指定的次要规则排序
sortField = second_order.split(":")[0];
sortOrder = second_order.split(":")[1].equals("desc") ? SortOrder.DESC : SortOrder.ASC;
productList = this.sortListBySortField(productList, viewNum, sortField, sortOrder);
// 4、获取最终结果
return this.getProductListResults(productList);
}
@Override
... ... @@ -213,7 +238,6 @@ public class AggProductListServiceImpl implements IAggProductListService, Applic
}
// 3、构造查询条件
SearchParam searchParam = new SearchParam();
//paramMap.put("promotion", null);
searchParam.setQuery(this.builderActivityQueryBuilder(paramMap));// 活动特定的个性化
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
searchParam.setSize(0);
... ... @@ -224,7 +248,7 @@ public class AggProductListServiceImpl implements IAggProductListService, Applic
if (searchCommonHelper.isNeedPersonalSearch(paramMap)) {
order = "_score:desc";
}
order = searchSortHelper.dealSortField(order,false);
order = searchSortHelper.dealSortField(order, false);
String sortField = order.split(":")[0];
SortOrder sortOrder = order.split(":")[1].equals("desc") ? SortOrder.DESC : SortOrder.ASC;
... ... @@ -257,7 +281,7 @@ public class AggProductListServiceImpl implements IAggProductListService, Applic
if (!aggMaps.containsKey(firstAggName)) {
return searchApiResult.setData("");
}
List<Map<String, Object>> productList = this.getProductListOrderByScore(((MultiBucketsAggregation) aggMaps.get(firstAggName)), pageSize, sortField, sortOrder);
List<Map<String, Object>> productList = this.getAggProductListByBrandResult(((MultiBucketsAggregation) aggMaps.get(firstAggName)), pageSize, sortField, sortOrder);
jsonObject = new JSONObject();
jsonObject.put("total", pageSize);
jsonObject.put("page", 1);
... ... @@ -273,42 +297,63 @@ public class AggProductListServiceImpl implements IAggProductListService, Applic
}
}
private List<Map<String, Object>> getProductListOrderByScore(final MultiBucketsAggregation aggregation, int viewNum, String sortField, SortOrder sortOrder) {
private List<Map<String, Object>> getAggProductListByBrandResult(final MultiBucketsAggregation aggregation, int viewNum, String sortField, SortOrder sortOrder) {
// 1、从聚合结果中获取原生数据
List<Map<String, Object>> productList = this.getProductListWithFromAggregation(aggregation);
// 2、按指定的排序规则排序
productList = this.sortListBySortField(productList, viewNum, sortField, sortOrder);
// 3、获取最终结果
return this.getProductListResults(productList);
}
/**
* 从聚合结果中获取原生的商品列表
*
* @param aggregation
* @return
*/
private List<Map<String, Object>> getProductListWithFromAggregation(final MultiBucketsAggregation aggregation) {
Iterator<? extends Bucket> itAgg = aggregation.getBuckets().iterator();
// 获取品牌聚合出来的商品
TopHits topHits;
SearchHits hits;
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
List<Map<String, Object>> dataList = new ArrayList<Map<String, Object>>();
List<Map<String, Object>> productList = new ArrayList<Map<String, Object>>();
while (itAgg.hasNext()) {
Bucket lt = itAgg.next();
if (lt.getAggregations().getAsMap().containsKey("product")) {
topHits = lt.getAggregations().get("product");
TopHits topHits = lt.getAggregations().get("product");
if (topHits != null) {
hits = topHits.getHits();
SearchHits hits = topHits.getHits();
for (SearchHit hit : hits.getHits()) {
Map<String, Object> source = hit.getSource();
float _score = hit.getScore();
source.put("_score", _score);
dataList.add(source);
productList.add(source);
}
}
}
}
dataList = this.sortListBySortField(dataList, viewNum, sortField, sortOrder);
return productList;
}
/**
* 组合productPlan
*
* @param productList
* @return
*/
private List<Map<String, Object>> getProductListResults(List<Map<String, Object>> productList) {
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
try {
List<String> sknStr = new ArrayList<String>();
for (Map<String, Object> data : dataList) {
for (Map<String, Object> data : productList) {
sknStr.add("" + data.get("productSkn"));
}
Map<String, List<Map<String, Object>>> productPricePlanMap = searchServiceHelper.searchProductPricePlan((String[]) sknStr.toArray(new String[sknStr.size()]));
for (Map<String, Object> m : dataList) {
result.add(searchServiceHelper.getProductMapWithPricePlan(m, productPricePlanMap));
for (Map<String, Object> m : productList) {
results.add(searchServiceHelper.getProductMapWithPricePlan(m, productPricePlanMap));
}
} catch (Exception e) {
logger.error("[func=aggProductList][Exception={}][begin={}]", e, System.currentTimeMillis());
}
return result;
return results;
}
private double getDouble(Object value) {
... ...