|
|
package com.yoho.search.service.servicenew.impl;
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
import java.util.Collections;
|
|
|
import java.util.Comparator;
|
|
|
import java.util.HashMap;
|
...
|
...
|
@@ -22,6 +23,7 @@ import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation.Buck |
|
|
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
|
|
|
import org.elasticsearch.search.aggregations.bucket.terms.TermsBuilder;
|
|
|
import org.elasticsearch.search.aggregations.metrics.tophits.TopHits;
|
|
|
import org.elasticsearch.search.sort.FieldSortBuilder;
|
|
|
import org.elasticsearch.search.sort.SortBuilders;
|
|
|
import org.elasticsearch.search.sort.SortOrder;
|
|
|
import org.slf4j.Logger;
|
...
|
...
|
@@ -46,8 +48,8 @@ import com.yoho.search.service.service.helper.SearchCommonHelper; |
|
|
import com.yoho.search.service.service.helper.SearchServiceHelper;
|
|
|
import com.yoho.search.service.service.helper.SearchSortHelper;
|
|
|
import com.yoho.search.service.servicenew.IAggProductListService;
|
|
|
import com.yoho.search.service.utils.SearchApiResultUtils;
|
|
|
import com.yoho.search.service.vo.SearchApiResult;
|
|
|
import com.yoho.search.service.vo.SearchSort;
|
|
|
|
|
|
@Service
|
|
|
public class AggProductListServiceImpl implements IAggProductListService, ApplicationEventPublisherAware {
|
...
|
...
|
@@ -85,230 +87,266 @@ 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 getTopHitsBucketSize(Map<String, String> paramMap) {
|
|
|
int topHitsSize = 1;
|
|
|
try {
|
|
|
topHitsSize = Integer.valueOf(paramMap.get("aggTypeSize"));
|
|
|
} catch (Exception e) {
|
|
|
}
|
|
|
if (topHitsSize <= 0) {
|
|
|
topHitsSize = 1;
|
|
|
}
|
|
|
return topHitsSize;
|
|
|
}
|
|
|
|
|
|
private SearchSort genSearchSort(String order) {
|
|
|
if (StringUtils.isBlank(order)) {
|
|
|
return null;
|
|
|
}
|
|
|
order = searchSortHelper.getLegalOrder(order, false);
|
|
|
if (StringUtils.isBlank(order)) {
|
|
|
return null;
|
|
|
}
|
|
|
String sortField = order.split(":")[0];
|
|
|
SortOrder sortOrder = order.split(":")[1].equals("desc") ? SortOrder.DESC : SortOrder.ASC;
|
|
|
return new SearchSort(sortField, sortOrder);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @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());
|
|
|
logger.info("[func=aggProductList][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
|
|
|
// 1、参数校验
|
|
|
String aggType = paramMap.get("aggType");// 获取聚合类型
|
|
|
if (StringUtils.isBlank(aggType) || !aggTypeToEsField.containsKey(aggType)) {
|
|
|
return new SearchApiResult().setCode(400).setData("聚合类型非法");
|
|
|
}
|
|
|
if (!paramMap.containsKey(aggType)) {
|
|
|
return new SearchApiResult().setCode(400).setData("请传对应聚合类型的参数");
|
|
|
}
|
|
|
|
|
|
// 1、参数校验
|
|
|
String aggType = paramMap.get("aggType");
|
|
|
if (StringUtils.isBlank(aggType) || !aggTypeToEsField.containsKey(aggType)) {
|
|
|
return new SearchApiResult().setCode(400).setData("聚合类型非法");
|
|
|
}
|
|
|
if (!paramMap.containsKey(aggType)) {
|
|
|
return new SearchApiResult().setCode(400).setData("请传对应聚合类型的参数");
|
|
|
}
|
|
|
// 2、获取第一个聚合的字段
|
|
|
String firstAggField = aggTypeToEsField.get(aggType);
|
|
|
|
|
|
// 2、构造核心参数
|
|
|
String[] values = paramMap.get(aggType).split(",");
|
|
|
int viewNum = (values == null ? 10 : values.length);
|
|
|
String firstAggFiled = aggTypeToEsField.get(aggType);
|
|
|
// 3、获取第一个聚合的桶大小
|
|
|
String[] aggTypeValues = paramMap.get(aggType).split(",");// 获取聚合类型的值
|
|
|
int firstAggBucketCount = (aggTypeValues == null ? 10 : aggTypeValues.length);// 获取聚合的桶大小
|
|
|
|
|
|
// 3、构造查询条件
|
|
|
SearchParam searchParam = new SearchParam();
|
|
|
//paramMap.put("promotion", null);
|
|
|
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));//活动特定的个性化
|
|
|
searchParam.setQuery(this.builderActivityQueryBuilder(paramMap));
|
|
|
searchParam.setSize(0);
|
|
|
// 4、获取聚合排序条件
|
|
|
String aggOrder = "sales_num:desc";
|
|
|
if (searchCommonHelper.isNeedPersonalSearch(paramMap)) {
|
|
|
aggOrder = "_score:desc";
|
|
|
}
|
|
|
SearchSort aggSort = this.genSearchSort(aggOrder);
|
|
|
String second_order = paramMap.get("second_order");
|
|
|
|
|
|
// 4、构造聚合条件
|
|
|
final String firstAggName = "firstAgg";
|
|
|
// 5、获取次要排序条件,主要用作顺序打乱
|
|
|
SearchSort secondSearchSort = this.genSearchSort(second_order);
|
|
|
|
|
|
List<AbstractAggregationBuilder> list = new ArrayList<AbstractAggregationBuilder>();
|
|
|
// 4.1)构造父聚合:品牌或品类聚合【同时按子聚合的sort字段排序】
|
|
|
TermsBuilder brandAggregationBuilder = AggregationBuilders.terms(firstAggName).field(firstAggFiled).order(Terms.Order.aggregation("sort", false)).size(viewNum);
|
|
|
// 4.2)添加子聚合:取得分最大的值
|
|
|
brandAggregationBuilder.subAggregation(AggregationBuilders.max("sort").field("_score"));
|
|
|
// 4.3)添加孙聚合:取打分最高的一个product
|
|
|
brandAggregationBuilder.subAggregation(AggregationBuilders.topHits("product").addSort(SortBuilders.fieldSort("_score").order(SortOrder.DESC)).setSize(1));
|
|
|
list.add(brandAggregationBuilder);
|
|
|
searchParam.setAggregationBuilders(list);
|
|
|
// 6、获取每个桶下面的商品数量
|
|
|
int topHitsBucketSize = this.getTopHitsBucketSize(paramMap);// 每个桶下面获取的商品数量
|
|
|
|
|
|
// 5、构造返回结果
|
|
|
SearchApiResult searchApiResult = new SearchApiResult().setMessage("agg productList list");
|
|
|
// 7、获取商品总数量
|
|
|
int totalViewNum = StringUtils.isBlank(paramMap.get("viewNum")) ? firstAggBucketCount * topHitsBucketSize : Integer.parseInt(paramMap.get("viewNum"));
|
|
|
|
|
|
// 6、先从缓存中获取,如果能取到,则直接返回
|
|
|
JSONObject jsonObject = searchCacheService.getJSONObjectFromCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
|
|
|
if (jsonObject != null) {
|
|
|
return searchApiResult.setData(jsonObject);
|
|
|
}
|
|
|
// 7、执行搜索,并构造返回结果
|
|
|
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
|
|
|
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
|
|
|
if (searchResult == null || searchResult.getAggMaps() == null) {
|
|
|
return searchApiResult.setData("");
|
|
|
}
|
|
|
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
|
|
|
if (!aggMaps.containsKey(firstAggName)) {
|
|
|
return searchApiResult.setData("");
|
|
|
}
|
|
|
List<Map<String, Object>> productList = this.getProductList(((MultiBucketsAggregation) aggMaps.get(firstAggName)));
|
|
|
// 8、执行查询
|
|
|
JSONObject jsonObject = this.getAggProductListJSONObject(paramMap, firstAggField, firstAggBucketCount, aggSort, topHitsBucketSize, secondSearchSort, totalViewNum);
|
|
|
if (jsonObject == null) {
|
|
|
jsonObject = new JSONObject();
|
|
|
jsonObject.put("total", productList == null ? 0 : productList.size());
|
|
|
jsonObject.put("page", 1);
|
|
|
jsonObject.put("page_size", viewNum);
|
|
|
jsonObject.put("page_total", 1);
|
|
|
jsonObject.put("product_list", productList);
|
|
|
searchCacheService.addJSONObjectToCache(indexName, searchParam, jsonObject);
|
|
|
return searchApiResult.setData(jsonObject);
|
|
|
} catch (Exception e) {
|
|
|
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_AGG_PRODUCTLIST.getEventName(), EventReportEnum.SEARCHCONTROLLER_AGG_PRODUCTLIST
|
|
|
.getFunctionName(), EventReportEnum.SEARCHCONTROLLER_AGG_PRODUCTLIST.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
|
|
|
return SearchApiResultUtils.errorSearchApiResult("aggProductList", paramMap, e);
|
|
|
}
|
|
|
return new SearchApiResult().setMessage("agg productList list").setData(jsonObject);
|
|
|
}
|
|
|
|
|
|
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());
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
/**
|
|
|
* @viewNum=10[总数]
|
|
|
* @aggTypeSize=1|2|3[每种个品牌下面最多的个数]
|
|
|
* @second_order=shelve_time:desc[次要排序条件]
|
|
|
*/
|
|
|
@Override
|
|
|
public SearchApiResult aggProductListByBrand(Map<String, String> paramMap) {
|
|
|
logger.info("[func=aggProductListByBrand][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
|
|
|
|
|
|
// 1、获取商品总数量参数
|
|
|
int totalViewNum = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
|
|
|
|
|
|
// 2、获取第一个聚合的字段
|
|
|
String firstAggField = "brandId";
|
|
|
|
|
|
// 3、获取第一个聚合的桶大小
|
|
|
int firstAggBucketCount = 200 + totalViewNum;
|
|
|
|
|
|
// 4、获取聚合排序条件
|
|
|
String aggOrder = "sales_num:desc";
|
|
|
if (searchCommonHelper.isNeedPersonalSearch(paramMap)) {
|
|
|
aggOrder = "_score:desc";
|
|
|
}
|
|
|
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());
|
|
|
SearchSort aggOrderSearchSort = this.genSearchSort(aggOrder);
|
|
|
|
|
|
// 5、获取次要排序条件,主要用作顺序打乱
|
|
|
String second_order = paramMap.get("second_order");
|
|
|
SearchSort secondSearchSort = this.genSearchSort(second_order);
|
|
|
|
|
|
// 6、获取每个桶下面的商品数量
|
|
|
int topHitsBucketSize = this.getTopHitsBucketSize(paramMap);// 每个桶下面获取的商品数量
|
|
|
|
|
|
// 7、执行搜索
|
|
|
JSONObject jsonObject = this.getAggProductListJSONObject(paramMap, firstAggField, firstAggBucketCount, aggOrderSearchSort, topHitsBucketSize, secondSearchSort,
|
|
|
totalViewNum);
|
|
|
if (jsonObject == null) {
|
|
|
jsonObject = new JSONObject();
|
|
|
}
|
|
|
return result;
|
|
|
return new SearchApiResult().setMessage("agg productList by brand list").setData(jsonObject);
|
|
|
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public SearchApiResult aggProductListByBrand(Map<String, String> paramMap) {
|
|
|
/**
|
|
|
* @param firstAggField
|
|
|
* 【父聚合的字段名称】
|
|
|
* @param firstAggBucketCount
|
|
|
* 【父聚合的桶大小】
|
|
|
* @param aggOrderSearchSort
|
|
|
* 【聚合排序规则,即按什么排序推荐】
|
|
|
* @param secondSearchSort
|
|
|
* 【次要排序条件,即最终商品按什么排序】
|
|
|
* @param totalViewNum
|
|
|
* 【最终返回的总数量】
|
|
|
* @return
|
|
|
*/
|
|
|
private JSONObject getAggProductListJSONObject(Map<String, String> paramMap, String firstAggField, int firstAggBucketCount, SearchSort aggSort, int topHitsBucketSize,
|
|
|
SearchSort secondSearchSort, int totalViewNum) {
|
|
|
try {
|
|
|
logger.info("[func=aggProductList][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
|
|
|
// 1、参数校验
|
|
|
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
|
|
|
int page = StringUtils.isBlank(paramMap.get("page")) ? 1 : Integer.parseInt(paramMap.get("page"));
|
|
|
if (page < 1 || pageSize < 0) {
|
|
|
throw new IllegalArgumentException("分页参数不合法");
|
|
|
}
|
|
|
if (pageSize > 60) {
|
|
|
pageSize = 60;
|
|
|
}
|
|
|
// 3、构造查询条件
|
|
|
// 1、构造查询条件
|
|
|
SearchParam searchParam = new SearchParam();
|
|
|
//paramMap.put("promotion", null);
|
|
|
searchParam.setQuery(this.builderActivityQueryBuilder(paramMap));// 活动特定的个性化
|
|
|
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
|
|
|
searchParam.setQuery(this.builderActivityQueryBuilder(paramMap));// 活动特定的个性化
|
|
|
searchParam.setSize(0);
|
|
|
|
|
|
// 4、构造聚合条件
|
|
|
final String firstAggName = "firstAgg";
|
|
|
String order = "sales_num:desc";
|
|
|
if (searchCommonHelper.isNeedPersonalSearch(paramMap)) {
|
|
|
order = "_score:desc";
|
|
|
// just for cache
|
|
|
searchParam.setOffset(totalViewNum);
|
|
|
if (secondSearchSort != null) {
|
|
|
searchParam.setSortBuilders(Arrays.asList(new FieldSortBuilder(secondSearchSort.getSortField()).order(secondSearchSort.getSortOrder())));
|
|
|
}
|
|
|
order = searchSortHelper.dealSortField(order,false);
|
|
|
String sortField = order.split(":")[0];
|
|
|
SortOrder sortOrder = order.split(":")[1].equals("desc") ? SortOrder.DESC : SortOrder.ASC;
|
|
|
|
|
|
// 2、构造聚合条件
|
|
|
final String firstAggName = "firstAgg";
|
|
|
List<AbstractAggregationBuilder> list = new ArrayList<AbstractAggregationBuilder>();
|
|
|
// 4.1)构造父聚合:品牌或品类聚合【同时按子聚合的sort字段排序】
|
|
|
TermsBuilder brandAggregationBuilder = AggregationBuilders.terms(firstAggName).field("brandId").order(Terms.Order.aggregation("sort", sortOrder.equals(SortOrder.ASC)))
|
|
|
.size(200 + pageSize);
|
|
|
// 4.2)添加子聚合:取得分最大的值
|
|
|
brandAggregationBuilder.subAggregation(AggregationBuilders.max("sort").field(sortField));
|
|
|
// 4.3)添加孙聚合:取打分最高的一个product
|
|
|
brandAggregationBuilder.subAggregation(AggregationBuilders.topHits("product").addSort(SortBuilders.fieldSort(sortField).order(sortOrder)).setSize(1));
|
|
|
list.add(brandAggregationBuilder);
|
|
|
// 2.1)构造父聚合:品牌或品类聚合【同时按子聚合的sort字段排序】
|
|
|
TermsBuilder firstAggregationBuilder = AggregationBuilders.terms(firstAggName).field(firstAggField).order(Terms.Order.aggregation("sort", aggSort.asc()))
|
|
|
.size(firstAggBucketCount);
|
|
|
// 2.2)添加子聚合:取得分最大的值
|
|
|
firstAggregationBuilder.subAggregation(AggregationBuilders.max("sort").field(aggSort.getSortField()));
|
|
|
// 2.3)添加孙聚合:取打分最高的一个product
|
|
|
firstAggregationBuilder.subAggregation(AggregationBuilders.topHits("product").addSort(SortBuilders.fieldSort(aggSort.getSortField()).order(aggSort.getSortOrder()))
|
|
|
.setSize(topHitsBucketSize));
|
|
|
list.add(firstAggregationBuilder);
|
|
|
searchParam.setAggregationBuilders(list);
|
|
|
|
|
|
// 5、构造返回结果
|
|
|
SearchApiResult searchApiResult = new SearchApiResult().setMessage("agg productList list");
|
|
|
|
|
|
// 6、先从缓存中获取,如果能取到,则直接返回
|
|
|
// 3、先从缓存中获取,如果能取到,则直接返回
|
|
|
JSONObject jsonObject = searchCacheService.getJSONObjectFromCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
|
|
|
if (jsonObject != null) {
|
|
|
return searchApiResult.setData(jsonObject);
|
|
|
return jsonObject;
|
|
|
}
|
|
|
// 7、执行搜索,并构造返回结果
|
|
|
// 4、执行搜索,并构造返回结果
|
|
|
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
|
|
|
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
|
|
|
if (searchResult == null || searchResult.getAggMaps() == null) {
|
|
|
return searchApiResult.setData("");
|
|
|
return null;
|
|
|
}
|
|
|
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
|
|
|
if (!aggMaps.containsKey(firstAggName)) {
|
|
|
return searchApiResult.setData("");
|
|
|
return null;
|
|
|
}
|
|
|
List<Map<String, Object>> productList = this.getProductListOrderByScore(((MultiBucketsAggregation) aggMaps.get(firstAggName)), pageSize, sortField, sortOrder);
|
|
|
// 5、构造返回结果
|
|
|
List<Map<String, Object>> productList = this.getAggProductListResult(((MultiBucketsAggregation) aggMaps.get(firstAggName)), totalViewNum, aggSort, secondSearchSort);
|
|
|
jsonObject = new JSONObject();
|
|
|
jsonObject.put("total", pageSize);
|
|
|
jsonObject.put("total", productList == null ? 0 : productList.size());
|
|
|
jsonObject.put("page", 1);
|
|
|
jsonObject.put("page_size", pageSize);
|
|
|
jsonObject.put("page_size", totalViewNum);
|
|
|
jsonObject.put("page_total", 1);
|
|
|
jsonObject.put("product_list", productList);
|
|
|
searchCacheService.addJSONObjectToCache(indexName, searchParam, jsonObject);
|
|
|
return searchApiResult.setData(jsonObject);
|
|
|
return jsonObject;
|
|
|
} catch (Exception e) {
|
|
|
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_AGG_PRODUCTLIST.getEventName(), EventReportEnum.SEARCHCONTROLLER_AGG_PRODUCTLIST
|
|
|
.getFunctionName(), EventReportEnum.SEARCHCONTROLLER_AGG_PRODUCTLIST.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
|
|
|
return SearchApiResultUtils.errorSearchApiResult("aggProductList", paramMap, e);
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private List<Map<String, Object>> getProductListOrderByScore(final MultiBucketsAggregation aggregation, int viewNum, String sortField, SortOrder sortOrder) {
|
|
|
private List<Map<String, Object>> getAggProductListResult(final MultiBucketsAggregation aggregation, int viewNum, SearchSort firstOrder, SearchSort secondOrder) {
|
|
|
// 1、从聚合结果中获取原生数据
|
|
|
List<Map<String, Object>> productList = this.getProductListWithFromAggregation(aggregation);
|
|
|
// 2、按指定的首要规则排序
|
|
|
productList = this.sortListBySortField(productList, viewNum, firstOrder);
|
|
|
// 3、按指定的次要规则排序
|
|
|
productList = this.sortListBySortField(productList, Integer.MAX_VALUE, secondOrder);
|
|
|
// 4、获取最终结果
|
|
|
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) {
|
...
|
...
|
@@ -333,25 +371,24 @@ public class AggProductListServiceImpl implements IAggProductListService, Applic |
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
private List<Map<String, Object>> sortListBySortField(List<Map<String, Object>> productList, int viewNum, String orderField, SortOrder sortOrder) {
|
|
|
if (productList == null || productList.isEmpty()) {
|
|
|
return new ArrayList<Map<String, Object>>();
|
|
|
private List<Map<String, Object>> sortListBySortField(List<Map<String, Object>> productList, int viewNum, SearchSort searchSort) {
|
|
|
if (productList == null || productList.isEmpty() || searchSort == null) {
|
|
|
return productList;
|
|
|
}
|
|
|
// 再按照某个字段对商品排序
|
|
|
boolean isDesc = sortOrder.equals(SortOrder.DESC) ? true : false;
|
|
|
|
|
|
boolean asc = searchSort.asc();
|
|
|
Collections.sort(productList, new Comparator<Map<String, Object>>() {
|
|
|
public int compare(Map<String, Object> o1, Map<String, Object> o2) {
|
|
|
try {
|
|
|
double value1 = getDouble(o1.get(orderField));
|
|
|
double value2 = getDouble(o2.get(orderField));
|
|
|
double value1 = getDouble(o1.get(searchSort.getSortField()));
|
|
|
double value2 = getDouble(o2.get(searchSort.getSortField()));
|
|
|
if (value1 == value2) {
|
|
|
return 0;
|
|
|
}
|
|
|
if (isDesc) {
|
|
|
return value1 - value2 > 0 ? -1 : 1;
|
|
|
} else {
|
|
|
if (asc) {
|
|
|
return value1 - value2 > 0 ? 1 : -1;
|
|
|
} else {
|
|
|
return value1 - value2 > 0 ? -1 : 1;
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
logger.error(e.getMessage(), e);
|
...
|
...
|
|