...
|
...
|
@@ -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) {
|
...
|
...
|
|