Authored by wangnan

group_brands,group_shops接口修改,返回中增加info信息

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;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.core.es.utils.IgnoreSomeException;
import com.yoho.search.service.cache.CacheEnum;
import com.yoho.search.service.service.AggregationService;
import com.yoho.search.service.service.SearchCacheService;
import com.yoho.search.service.service.SearchCommonService;
import com.yoho.search.service.service.helper.SearchServiceHelper;
import com.yoho.search.service.service.helper.SearchSortHelper;
import com.yoho.search.service.servicenew.IBrandService;
import com.yoho.search.service.utils.HttpServletRequestUtils;
import com.yoho.search.service.utils.SearchApiResultUtils;
import com.yoho.search.service.vo.SearchApiResult;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
... ... @@ -36,581 +41,580 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.core.es.utils.IgnoreSomeException;
import com.yoho.search.service.cache.CacheEnum;
import com.yoho.search.service.service.AggregationService;
import com.yoho.search.service.service.SearchCacheService;
import com.yoho.search.service.service.SearchCommonService;
import com.yoho.search.service.service.helper.SearchServiceHelper;
import com.yoho.search.service.service.helper.SearchSortHelper;
import com.yoho.search.service.servicenew.IBrandService;
import com.yoho.search.service.utils.HttpServletRequestUtils;
import com.yoho.search.service.utils.SearchApiResultUtils;
import com.yoho.search.service.vo.SearchApiResult;
import java.util.*;
import java.util.Map.Entry;
@Service
public class BrandServiceImpl implements IBrandService, ApplicationEventPublisherAware {
private static final Logger logger = LoggerFactory.getLogger(BrandServiceImpl.class);
private static Logger CACHE_MATCH_REQUEST = LoggerFactory.getLogger("CACHE_MATCH_REQUEST");
@Autowired
private SearchSortHelper searchSortHelper;
@Autowired
private SearchServiceHelper searchServiceHelper;
@Autowired
private AggregationService aggregationService;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchCacheService searchCacheService;
private static final CacheEnum brandCacheEnum = CacheEnum.EHCACHE;
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
@Override
public SearchApiResult aggBrand(Map<String, String> paramMap) {
try {
logger.info("[func=aggBrand][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
// 1、从缓存中获取
SearchParam searchParamClone = searchParam.clone();
JSONArray cacheJSONArray = searchCacheService.getJSONArrayFromCache(brandCacheEnum, indexName, searchParamClone);
if (cacheJSONArray != null) {
CACHE_MATCH_REQUEST.info("match cache , url is :/productindex/aggBrand.json?" + HttpServletRequestUtils.genParamString(paramMap));
return new SearchApiResult().setData(cacheJSONArray);
}
// 2、从ES中获取
JSONObject jsonObject = aggregationService.getBrandAggregationResultWithOutCache(searchParam, paramMap, true);
if (jsonObject == null) {
return new SearchApiResult().setData(500).setMessage("exception");
}
// 3、生成结果并且加入缓存
JSONArray brandJSONArray = jsonObject.getJSONArray("brandAgg");
if (brandJSONArray != null) {
searchCacheService.addJSONArrayToCache(brandCacheEnum, indexName, searchParamClone, brandJSONArray);
}
return new SearchApiResult().setData(brandJSONArray);
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult("aggBrand", paramMap, e);
}
}
@Override
public SearchApiResult brands(Map<String, String> paramMap) {
try {
logger.info("[func=brands][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、构造查询参数
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
// 2、构造聚合参数
List<AbstractAggregationBuilder> list = new ArrayList<AbstractAggregationBuilder>();
list.add(AggregationBuilders.terms("brandAlifAgg").field("brandAlif").size(1000).order(Terms.Order.term(true))
.subAggregation(AggregationBuilders.terms("brandAgg").field("brandId").size(1000)));
searchParam.setAggregationBuilders(list);
searchParam.setSize(0);
// 3、brand数据量比较大,走本地缓存
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(brandCacheEnum, indexName, searchParam);
if (cacheObject != null) {
CACHE_MATCH_REQUEST.info("match cache , url is :/brands.json?" + HttpServletRequestUtils.genParamString(paramMap));
return new SearchApiResult().setData(cacheObject);
}
// 4、查询ES
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
SearchApiResult searchApiResult = new SearchApiResult().setMessage("brand List.");
if (searchResult == null || searchResult.getAggMaps() == null) {
return searchApiResult.setCode(500);
}
Map<String, Aggregation> aggregationResult = searchResult.getAggMaps();
if (!aggregationResult.containsKey("brandAlifAgg")) {
return searchApiResult;
}
// 5、构造返回结果并加入缓存
JSONObject result = new JSONObject();
result.put("brands", makeBrandResponse(((MultiBucketsAggregation) aggregationResult.get("brandAlifAgg"))));
searchCacheService.addJSONObjectToCache(brandCacheEnum, indexName, searchParam, result);
return searchApiResult.setData(result);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_BRANDS.getEventName(), EventReportEnum.SEARCHCONTROLLER_BRANDS.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_BRANDS.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("brands", paramMap, e);
}
}
/**
* 制作品牌报文
*/
private Map<String, JSONArray> makeBrandResponse(MultiBucketsAggregation aggregation) throws Exception {
// 1)获取每个brandAlif对应的brandIds
Map<String, List<String>> brandAlif2BrandIds = new LinkedHashMap<String, List<String>>();
for (Bucket brandAlifBucket : aggregation.getBuckets()) {
String brandAlif = brandAlifBucket.getKeyAsString();
List<String> brandIds = new ArrayList<String>();
MultiBucketsAggregation brandAggs = (MultiBucketsAggregation) brandAlifBucket.getAggregations().asMap().get("brandAgg");
for (Bucket brandIdBucket : brandAggs.getBuckets()) {
brandIds.addAll(Arrays.asList(brandIdBucket.getKeyAsString().split(",")));
}
brandAlif2BrandIds.put(brandAlif, brandIds);
}
// 2)获取所有的品牌id
Set<String> brandIdSet = new HashSet<String>();
for (Map.Entry<String, List<String>> entry : brandAlif2BrandIds.entrySet()) {
brandIdSet.addAll(entry.getValue());
}
// 3)获取所有的品牌数据
JSONArray jsonArray = searchCommonService.doMultiGet(ISearchConstants.INDEX_NAME_BRAND, brandIdSet, null);
Map<String, JSONObject> brandIdMap = new HashMap<String, JSONObject>();
for (int index = 0; index < jsonArray.size(); index++) {
JSONObject brandJSONObject = jsonArray.getJSONObject(index);
brandIdMap.put(brandJSONObject.getString("id"), brandJSONObject);
}
// 4)构造真正的数据
Map<String, JSONArray> result = new LinkedHashMap<String, JSONArray>();
for (Map.Entry<String, List<String>> entry : brandAlif2BrandIds.entrySet()) {
String brandAlif = entry.getKey();
JSONArray brands = new JSONArray();
for (String brandId : entry.getValue()) {
JSONObject brand = brandIdMap.get(brandId);
if (brand != null) {
brands.add(brand);
}
}
result.put(brandAlif, brands);
}
return result;
}
@Override
public SearchApiResult brandList(Map<String, String> paramMap) {
try {
logger.info("[func=brandList][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1)构建参数
SearchParam searchParam = new SearchParam();
searchParam.setSize(10000);
searchParam.setQuery(QueryBuilders.matchAllQuery());
// 2、brand数据量比较大,走本地缓存。guavacache缓存中获取result,没有到es中获取
final String indexName = ISearchConstants.INDEX_NAME_BRAND;
JSONArray cacheJSONArray = searchCacheService.getJSONArrayFromCache(brandCacheEnum, indexName, searchParam);
if (cacheJSONArray != null) {
CACHE_MATCH_REQUEST.info("match cache , url is :/brand/list.json?" + HttpServletRequestUtils.genParamString(paramMap));
return new SearchApiResult().setData(cacheJSONArray);
}
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_BRAND, searchParam);
if (searchResult == null || searchResult.getResultList().isEmpty()) {
return new SearchApiResult().setData(400).setMessage("empty result");
}
List<Map<String, Object>> result = searchResult.getResultList();
JSONArray jsonArray = new JSONArray();
for (Map<String, Object> map : result) {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("id", map.get("id"));
dataMap.put("brand_alif", map.get("brandAlif"));
dataMap.put("brand_name_en", map.get("brandNameEn"));
dataMap.put("brand_domain", map.get("brandDomain"));
dataMap.put("is_hot", map.get("isHot"));
dataMap.put("hot_keyword", map.get("hotKeyword"));
dataMap.put("brand_name_cn", map.get("brandNameCn"));
dataMap.put("brand_ico", map.get("brandIco"));
dataMap.put("brand_name", map.get("brandName"));
dataMap.put("brand_keyword", map.get("brandKeyword"));
jsonArray.add(dataMap);
}
searchCacheService.addJSONArrayToCache(brandCacheEnum, indexName, searchParam, jsonArray);
return new SearchApiResult().setMessage("brands info").setData(jsonArray);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.BRANDCONTROLLER_BRAND_LIST.getEventName(), EventReportEnum.BRANDCONTROLLER_BRAND_LIST.getFunctionName(),
EventReportEnum.BRANDCONTROLLER_BRAND_LIST.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("brandList", paramMap, e);
}
}
@Override
public SearchApiResult groupBrands(Map<String, String> paramMap) {
try {
logger.info("[func=groupBrands][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、参数检验
if (!paramMap.containsKey("brand")) {
return new SearchApiResult().setCode(400).setMessage("没有 brand参数 ");
}
// 2、构造通用参数
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
// 3、取每个品牌需要hit到的viewNum个产品数量
TermsBuilder aggregationBuilder = AggregationBuilders.terms("brandAgg").field("brandId").size(100);
int size = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
if (size > 0) {
aggregationBuilder.subAggregation(AggregationBuilders.topHits("product").setSize(size));
}
searchParam.setAggregationBuilders(Arrays.asList(aggregationBuilder));
searchParam.setSize(0);
// 4、构造返回结果
SearchApiResult searchApiResult = new SearchApiResult().setMessage("groupBrands List.");
// 5、先从缓存中获取,如果能取到,则直接返回
JSONObject jsonObject = searchCacheService.getJSONObjectFromCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (jsonObject != null) {
CACHE_MATCH_REQUEST.info("match cache , url is :/group_brands.json?" + HttpServletRequestUtils.genParamString(paramMap));
return searchApiResult.setData(jsonObject);
}
// 6、ES查询
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null) {
return searchApiResult.setData("");
}
// 7、构造结果并将结果存进缓存
JSONObject result = new JSONObject();
result.put("total", searchResult.getTotal());
if (searchResult.getAggMaps() != null) {
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
if (aggMaps.containsKey("brandAgg")) {
result.put("brands", getGroupBrandResponseMap(((MultiBucketsAggregation) aggMaps.get("brandAgg")), size));
}
}
searchCacheService.addJSONObjectToCache(indexName, searchParam, result);
return searchApiResult.setData(result);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_GROUP_BRANDS.getEventName(), EventReportEnum.SEARCHCONTROLLER_GROUP_BRANDS.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_GROUP_BRANDS.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("groupBrands", paramMap, e);
}
}
private Map<String, Object> getGroupBrandResponseMap(MultiBucketsAggregation aggregation, int size) {
Iterator<? extends Bucket> itAgg = aggregation.getBuckets().iterator();
Map<String, Object> dataMap = new HashMap<String, Object>();
Map<String, List<Map<String, Object>>> brand_ProductListMap = new HashMap<String, List<Map<String, Object>>>();
Map<String, Map<String, Object>> brand_ResultMap = new HashMap<String, Map<String, Object>>();
List<String> sknStr = new ArrayList<String>();
while (itAgg.hasNext()) {
Bucket lt = itAgg.next();
// 先处理每个品牌的数量
Map<String, Object> tempResult = new HashMap<String, Object>();
tempResult.put("count", lt.getDocCount());
brand_ResultMap.put(lt.getKeyAsString(), tempResult);
// 再处理每个品牌取得商品数量
if (size != 0) {
List<Map<String, Object>> dataList = new ArrayList<Map<String, Object>>();
if (lt.getAggregations().getAsMap().containsKey("product")) {
TopHits topHits = lt.getAggregations().get("product");
SearchHits hits = topHits.getHits();
for (SearchHit hit : hits.getHits()) {
sknStr.add("" + hit.getSource().get("productSkn"));
dataList.add(hit.getSource());
}
brand_ProductListMap.put(lt.getKeyAsString(), dataList);
}
}
}
try {
Map<String, List<Map<String, Object>>> productPricePlanMap = searchServiceHelper.searchProductPricePlan((String[]) sknStr.toArray(new String[sknStr.size()]));
brand_ResultMap.forEach((k, m) -> {
List<Map<String, Object>> productList = brand_ProductListMap.get(k);
if (productList == null) {
productList = new ArrayList<Map<String, Object>>();
}
List<Map<String, Object>> newProductList = new ArrayList<Map<String, Object>>();
for (Map<String, Object> productMap : productList) {
newProductList.add(searchServiceHelper.getProductMapWithPricePlan(productMap, productPricePlanMap));
}
m.put("product_list", newProductList);
dataMap.put(k, m);
});
} catch (Exception e) {
logger.error("[func=getGroupBrandResponseMap]" + e.getMessage(), e);
}
return dataMap;
}
@Override
public SearchApiResult aggProductsByBrandId(Map<String, String> paramMap) {
try {
logger.info("[func=aggProductsByBrandId][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、参数校验
String sortField = searchSortHelper.getLegalOrder(paramMap);
if (StringUtils.isBlank(sortField)) {
sortField = "shelveTime:desc";
}
String[] sortParts = sortField.split(":");
String realSortField = sortParts[0];
String realSortType = sortParts[1];
// 2、构造查询条件
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
searchParam.setSize(0);
// 3、获取要取的品牌商品数量
int viewNum = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
if (viewNum > 100) {
viewNum = 100;
}
// 4、构造聚合条件
List<AbstractAggregationBuilder> list = new ArrayList<AbstractAggregationBuilder>();
boolean isAscOrder = SortOrder.ASC.toString().equalsIgnoreCase(realSortType);
// 4.1)构造父聚合:品牌聚合【同时按子聚合的sort字段排序】
TermsBuilder brandAggregationBuilder = AggregationBuilders.terms("brandAgg").field("brandId").order(Terms.Order.aggregation("sort", isAscOrder)).size(viewNum);
// 4.2)添加子聚合:sort值为sortFieldName的最大值或最小值,给父聚合排序用
if (isAscOrder) {
brandAggregationBuilder.subAggregation(AggregationBuilders.min("sort").field(realSortField));
} else {
brandAggregationBuilder.subAggregation(AggregationBuilders.max("sort").field(realSortField));
}
// 4.3)添加孙聚合:按sort取一个product
brandAggregationBuilder.subAggregation(AggregationBuilders.topHits("product")
.addSort(SortBuilders.fieldSort(realSortField).order(isAscOrder ? SortOrder.ASC : SortOrder.DESC)).setSize(1));
list.add(brandAggregationBuilder);
searchParam.setAggregationBuilders(list);
// 5、构造返回结果
SearchApiResult searchApiResult = new SearchApiResult().setMessage("new-shelve list");
// 6、先从缓存中获取,如果能取到,则直接返回
JSONArray jsonArray = searchCacheService.getJSONArrayFromCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (jsonArray != null) {
CACHE_MATCH_REQUEST.info("match cache , url is :/new-shelve.json?" + HttpServletRequestUtils.genParamString(paramMap));
return searchApiResult.setData(jsonArray);
}
// 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("brandAgg")) {
return searchApiResult.setData("");
}
JSONArray productList = this.getNewShelveResponseMap(((MultiBucketsAggregation) aggMaps.get("brandAgg")));
searchCacheService.addJSONArrayToCache(indexName, searchParam, productList);
return searchApiResult.setData(productList);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_NEW_SHELVE.getEventName(), EventReportEnum.SEARCHCONTROLLER_NEW_SHELVE.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_NEW_SHELVE.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("searchNewestProductWithDiffBrand", paramMap, e);
}
}
private JSONArray getNewShelveResponseMap(final MultiBucketsAggregation aggregation) {
Iterator<? extends Bucket> itAgg = aggregation.getBuckets().iterator();
// 获取品牌聚合出来的商品
TopHits topHits;
SearchHits hits;
JSONArray result = new JSONArray();
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=getNewShelveResponseMap][Exception={}][begin={}]", e, System.currentTimeMillis());
}
return result;
}
@Override
public SearchApiResult aggProductsByBrandIdInParam(Map<String, String> paramMap) {
try {
logger.info("[func=aggProductsByBrandIdInParam][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、参数校验
if (!paramMap.containsKey("brand")) {
return new SearchApiResult().setCode(400).setMessage("没有 brand参数 ");
}
// 2、处理排序方式
String sortField = searchSortHelper.getLegalOrder(paramMap);
if (StringUtils.isBlank(sortField)) {
sortField = "shelveTime:desc";
}
String[] sortParts = sortField.split(":");
String realSortField = sortParts[0];
String realSortType = sortParts[1];
SortOrder realSortOrder = SortOrder.ASC.toString().equalsIgnoreCase(realSortType) ? SortOrder.ASC : SortOrder.DESC;
// 3、构造查询参数
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
// 4、构造聚合参数
List<AbstractAggregationBuilder> list = new ArrayList<AbstractAggregationBuilder>();
// 获取取商品的数量
// 构造品牌聚合参数[最多取100个品牌的一个商品,取回来之后再做排序]
TermsBuilder brandAggregationBuilder = AggregationBuilders.terms("brandAgg").field("brandId").size(100);
// 再构造对应HIT到的商品的聚合参数
FieldSortBuilder productSortBuilder = SortBuilders.fieldSort(realSortField).order(realSortOrder);
TopHitsBuilder productTopHitsBuilder = AggregationBuilders.topHits("product").addSort(productSortBuilder).setSize(1);
brandAggregationBuilder.subAggregation(productTopHitsBuilder);
list.add(brandAggregationBuilder);
searchParam.setAggregationBuilders(list);
// 5、设置报文缓存参数
int limit = StringUtils.isBlank(paramMap.get("limit")) ? 1 : Integer.parseInt(paramMap.get("limit"));
searchParam.setOffset(limit);// 这个参数只是用来生成报文以做缓存,不要动
searchParam.setSize(0);
// 6、构造返回结果
SearchApiResult searchApiResult = new SearchApiResult().setMessage("new product List.");
// 7、先从缓存中获取,如果能取到,则直接返回
JSONArray jsonArray = searchCacheService.getJSONArrayFromCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (jsonArray != null) {
CACHE_MATCH_REQUEST.info("match cache , url is :/new_product.json?" + HttpServletRequestUtils.genParamString(paramMap));
return searchApiResult.setData(jsonArray);
}
// 8、查询ES数据
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("brandAgg")) {
return searchApiResult.setData("");
}
// 9、构造返回数据并加入缓存
jsonArray = getNewBrandResponseMap(((MultiBucketsAggregation) aggMaps.get("brandAgg")), limit, paramMap.get("brand"), realSortField, realSortOrder);
searchCacheService.addJSONArrayToCache(indexName, searchParam, jsonArray);
return searchApiResult.setData(jsonArray);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_NEW_PRODUCT.getEventName(), EventReportEnum.SEARCHCONTROLLER_NEW_PRODUCT.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_NEW_PRODUCT.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("searchNewestProductWithDiffBrand", paramMap, e);
}
}
private JSONArray getNewBrandResponseMap(MultiBucketsAggregation aggregation, int size, String brands, final String realSortField, final SortOrder realSortOrder) {
Iterator<? extends Bucket> itAgg = aggregation.getBuckets().iterator();
// 首先获取全部品牌的商品列表
Map<String, Map<String, Object>> brandMap = new HashMap<String, Map<String, Object>>();
List<String> sknStr = new ArrayList<String>();
Map<String, Map<String, Object>> dataList = new HashMap<String, Map<String, Object>>();
while (itAgg.hasNext()) {
Bucket lt = itAgg.next();
if (lt.getAggregations().getAsMap().containsKey("product")) {
TopHits topHits = lt.getAggregations().get("product");
if (topHits != null) {
SearchHits hits = topHits.getHits();
for (SearchHit hit : hits.getHits()) {
sknStr.add("" + hit.getSource().get("productSkn"));
dataList.put(lt.getKeyAsString(), hit.getSource());
}
}
}
}
try {
Map<String, List<Map<String, Object>>> productPricePlanMap = searchServiceHelper.searchProductPricePlan((String[]) sknStr.toArray(new String[sknStr.size()]));
dataList.forEach((k, m) -> {
brandMap.put(k, searchServiceHelper.getProductMapWithPricePlan(m, productPricePlanMap));
});
} catch (Exception e) {
logger.error("[func=getNewBrandResponseMap][Exception={}][begin={}]", e, System.currentTimeMillis());
}
// 获取前面“size”个品牌的商品
if (brandMap.size() == 0) {
return new JSONArray();
}
// 购造商品列表
List<Map<String, Object>> productList = new ArrayList<Map<String, Object>>();
String[] brandIds = brands.split(",");
if (brandIds.length < size || brandMap.size() <= size) {
for (Entry<String, Map<String, Object>> entry : brandMap.entrySet()) {
productList.add(entry.getValue());
}
} else {
int num = 0;
int i = 0;
while (num < size) {
if (brandMap.containsKey(brandIds[i])) {
productList.add(brandMap.get(brandIds[i]));
num++;
}
i++;
}
}
// 再按照某个字段对商品排序
Collections.sort(productList, new Comparator<Map<String, Object>>() {
public int compare(Map<String, Object> o1, Map<String, Object> o2) {
Object realSortFieldValue1 = o1.get(realSortField);
Object realSortFieldValue2 = o1.get(realSortField);
int map1value = getIntValue(realSortFieldValue1);
int map2value = getIntValue(realSortFieldValue2);
if ("desc".equalsIgnoreCase(realSortOrder.name())) {
return map2value - map1value;
} else {
return map1value - map2value;
}
}
});
JSONArray jsonArray = new JSONArray();
jsonArray.addAll(productList);
return jsonArray;
}
private int getIntValue(Object value) {
if (value == null) {
return 0;
}
try {
return Integer.parseInt(value.toString());
} catch (Exception e) {
return 0;
}
}
private static final Logger logger = LoggerFactory.getLogger(BrandServiceImpl.class);
private static Logger CACHE_MATCH_REQUEST = LoggerFactory.getLogger("CACHE_MATCH_REQUEST");
@Autowired
private SearchSortHelper searchSortHelper;
@Autowired
private SearchServiceHelper searchServiceHelper;
@Autowired
private AggregationService aggregationService;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchCacheService searchCacheService;
private static final CacheEnum brandCacheEnum = CacheEnum.EHCACHE;
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
@Override
public SearchApiResult aggBrand(Map<String, String> paramMap) {
try {
logger.info("[func=aggBrand][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
// 1、从缓存中获取
SearchParam searchParamClone = searchParam.clone();
JSONArray cacheJSONArray = searchCacheService.getJSONArrayFromCache(brandCacheEnum, indexName, searchParamClone);
if (cacheJSONArray != null) {
CACHE_MATCH_REQUEST.info("match cache , url is :/productindex/aggBrand.json?" + HttpServletRequestUtils.genParamString(paramMap));
return new SearchApiResult().setData(cacheJSONArray);
}
// 2、从ES中获取
JSONObject jsonObject = aggregationService.getBrandAggregationResultWithOutCache(searchParam, paramMap, true);
if (jsonObject == null) {
return new SearchApiResult().setData(500).setMessage("exception");
}
// 3、生成结果并且加入缓存
JSONArray brandJSONArray = jsonObject.getJSONArray("brandAgg");
if (brandJSONArray != null) {
searchCacheService.addJSONArrayToCache(brandCacheEnum, indexName, searchParamClone, brandJSONArray);
}
return new SearchApiResult().setData(brandJSONArray);
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult("aggBrand", paramMap, e);
}
}
@Override
public SearchApiResult brands(Map<String, String> paramMap) {
try {
logger.info("[func=brands][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、构造查询参数
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
// 2、构造聚合参数
List<AbstractAggregationBuilder> list = new ArrayList<AbstractAggregationBuilder>();
list.add(AggregationBuilders.terms("brandAlifAgg").field("brandAlif").size(1000).order(Terms.Order.term(true))
.subAggregation(AggregationBuilders.terms("brandAgg").field("brandId").size(1000)));
searchParam.setAggregationBuilders(list);
searchParam.setSize(0);
// 3、brand数据量比较大,走本地缓存
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(brandCacheEnum, indexName, searchParam);
if (cacheObject != null) {
CACHE_MATCH_REQUEST.info("match cache , url is :/brands.json?" + HttpServletRequestUtils.genParamString(paramMap));
return new SearchApiResult().setData(cacheObject);
}
// 4、查询ES
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
SearchApiResult searchApiResult = new SearchApiResult().setMessage("brand List.");
if (searchResult == null || searchResult.getAggMaps() == null) {
return searchApiResult.setCode(500);
}
Map<String, Aggregation> aggregationResult = searchResult.getAggMaps();
if (!aggregationResult.containsKey("brandAlifAgg")) {
return searchApiResult;
}
// 5、构造返回结果并加入缓存
JSONObject result = new JSONObject();
result.put("brands", makeBrandResponse(((MultiBucketsAggregation) aggregationResult.get("brandAlifAgg"))));
searchCacheService.addJSONObjectToCache(brandCacheEnum, indexName, searchParam, result);
return searchApiResult.setData(result);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_BRANDS.getEventName(), EventReportEnum.SEARCHCONTROLLER_BRANDS.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_BRANDS.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("brands", paramMap, e);
}
}
/**
* 制作品牌报文
*/
private Map<String, JSONArray> makeBrandResponse(MultiBucketsAggregation aggregation) throws Exception {
// 1)获取每个brandAlif对应的brandIds
Map<String, List<String>> brandAlif2BrandIds = new LinkedHashMap<String, List<String>>();
for (Bucket brandAlifBucket : aggregation.getBuckets()) {
String brandAlif = brandAlifBucket.getKeyAsString();
List<String> brandIds = new ArrayList<String>();
MultiBucketsAggregation brandAggs = (MultiBucketsAggregation) brandAlifBucket.getAggregations().asMap().get("brandAgg");
for (Bucket brandIdBucket : brandAggs.getBuckets()) {
brandIds.addAll(Arrays.asList(brandIdBucket.getKeyAsString().split(",")));
}
brandAlif2BrandIds.put(brandAlif, brandIds);
}
// 2)获取所有的品牌id
Set<String> brandIdSet = new HashSet<String>();
for (Map.Entry<String, List<String>> entry : brandAlif2BrandIds.entrySet()) {
brandIdSet.addAll(entry.getValue());
}
// 3)获取所有的品牌数据
JSONArray jsonArray = searchCommonService.doMultiGet(ISearchConstants.INDEX_NAME_BRAND, brandIdSet, null);
Map<String, JSONObject> brandIdMap = new HashMap<String, JSONObject>();
for (int index = 0; index < jsonArray.size(); index++) {
JSONObject brandJSONObject = jsonArray.getJSONObject(index);
brandIdMap.put(brandJSONObject.getString("id"), brandJSONObject);
}
// 4)构造真正的数据
Map<String, JSONArray> result = new LinkedHashMap<String, JSONArray>();
for (Map.Entry<String, List<String>> entry : brandAlif2BrandIds.entrySet()) {
String brandAlif = entry.getKey();
JSONArray brands = new JSONArray();
for (String brandId : entry.getValue()) {
JSONObject brand = brandIdMap.get(brandId);
if (brand != null) {
brands.add(brand);
}
}
result.put(brandAlif, brands);
}
return result;
}
@Override
public SearchApiResult brandList(Map<String, String> paramMap) {
try {
logger.info("[func=brandList][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1)构建参数
SearchParam searchParam = new SearchParam();
searchParam.setSize(10000);
searchParam.setQuery(QueryBuilders.matchAllQuery());
// 2、brand数据量比较大,走本地缓存。guavacache缓存中获取result,没有到es中获取
final String indexName = ISearchConstants.INDEX_NAME_BRAND;
JSONArray cacheJSONArray = searchCacheService.getJSONArrayFromCache(brandCacheEnum, indexName, searchParam);
if (cacheJSONArray != null) {
CACHE_MATCH_REQUEST.info("match cache , url is :/brand/list.json?" + HttpServletRequestUtils.genParamString(paramMap));
return new SearchApiResult().setData(cacheJSONArray);
}
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_BRAND, searchParam);
if (searchResult == null || searchResult.getResultList().isEmpty()) {
return new SearchApiResult().setData(400).setMessage("empty result");
}
List<Map<String, Object>> result = searchResult.getResultList();
JSONArray jsonArray = new JSONArray();
for (Map<String, Object> map : result) {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("id", map.get("id"));
dataMap.put("brand_alif", map.get("brandAlif"));
dataMap.put("brand_name_en", map.get("brandNameEn"));
dataMap.put("brand_domain", map.get("brandDomain"));
dataMap.put("is_hot", map.get("isHot"));
dataMap.put("hot_keyword", map.get("hotKeyword"));
dataMap.put("brand_name_cn", map.get("brandNameCn"));
dataMap.put("brand_ico", map.get("brandIco"));
dataMap.put("brand_name", map.get("brandName"));
dataMap.put("brand_keyword", map.get("brandKeyword"));
jsonArray.add(dataMap);
}
searchCacheService.addJSONArrayToCache(brandCacheEnum, indexName, searchParam, jsonArray);
return new SearchApiResult().setMessage("brands info").setData(jsonArray);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.BRANDCONTROLLER_BRAND_LIST.getEventName(), EventReportEnum.BRANDCONTROLLER_BRAND_LIST.getFunctionName(),
EventReportEnum.BRANDCONTROLLER_BRAND_LIST.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("brandList", paramMap, e);
}
}
@Override
public SearchApiResult groupBrands(Map<String, String> paramMap) {
try {
logger.info("[func=groupBrands][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、参数检验
if (!paramMap.containsKey("brand")) {
return new SearchApiResult().setCode(400).setMessage("没有 brand参数 ");
}
// 2、构造通用参数
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
// 3、取每个品牌需要hit到的viewNum个产品数量
TermsBuilder aggregationBuilder = AggregationBuilders.terms("brandAgg").field("brandId").size(100);
int size = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
if (size > 0) {
aggregationBuilder.subAggregation(AggregationBuilders.topHits("product").setSize(size));
}
searchParam.setAggregationBuilders(Arrays.asList(aggregationBuilder));
searchParam.setSize(0);
// 4、构造返回结果
SearchApiResult searchApiResult = new SearchApiResult().setMessage("groupBrands List.");
// 5、先从缓存中获取,如果能取到,则直接返回
JSONObject jsonObject = searchCacheService.getJSONObjectFromCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (jsonObject != null) {
CACHE_MATCH_REQUEST.info("match cache , url is :/group_brands.json?" + HttpServletRequestUtils.genParamString(paramMap));
return searchApiResult.setData(jsonObject);
}
// 6、ES查询 Productindex
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null) {
return searchApiResult.setData("");
}
//7.ES查询 brand
SearchApiResult searchApiResultBrands = brandList(paramMap);
Map<String, Map<String, Object>> brandMap = new HashMap<>();
if (searchApiResultBrands.getData() != null) {
JSONArray jsonArrayBrands = (JSONArray) searchApiResultBrands.getData();
Iterator<Object> it = jsonArrayBrands.iterator();
while (it.hasNext()) {
Map<String, Object> dataMap = (Map<String, Object>) it.next();
brandMap.put(dataMap.get("id").toString(), dataMap);
}
}
// 8、构造结果并将结果存进缓存
JSONObject result = new JSONObject();
result.put("total", searchResult.getTotal());
if (searchResult.getAggMaps() != null) {
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
if (aggMaps.containsKey("brandAgg")) {
result.put("brands", getGroupBrandResponseMap(((MultiBucketsAggregation) aggMaps.get("brandAgg")), brandMap, size));
}
}
searchCacheService.addJSONObjectToCache(indexName, searchParam, result);
return searchApiResult.setData(result);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_GROUP_BRANDS.getEventName(), EventReportEnum.SEARCHCONTROLLER_GROUP_BRANDS.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_GROUP_BRANDS.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("groupBrands", paramMap, e);
}
}
private Map<String, Object> getGroupBrandResponseMap(MultiBucketsAggregation aggregation, Map<String, Map<String, Object>> brandMap, int size) {
Iterator<? extends Bucket> itAgg = aggregation.getBuckets().iterator();
Map<String, Object> dataMap = new HashMap<String, Object>();
Map<String, List<Map<String, Object>>> brand_ProductListMap = new HashMap<String, List<Map<String, Object>>>();
Map<String, Map<String, Object>> brand_ResultMap = new HashMap<String, Map<String, Object>>();
List<String> sknStr = new ArrayList<String>();
while (itAgg.hasNext()) {
Bucket lt = itAgg.next();
// 先处理每个品牌的数量
Map<String, Object> tempResult = new HashMap<String, Object>();
tempResult.put("count", lt.getDocCount());
// 再处理每个品牌取得商品数量
if (size != 0) {
List<Map<String, Object>> dataList = new ArrayList<Map<String, Object>>();
if (lt.getAggregations().getAsMap().containsKey("product")) {
TopHits topHits = lt.getAggregations().get("product");
SearchHits hits = topHits.getHits();
for (SearchHit hit : hits.getHits()) {
sknStr.add("" + hit.getSource().get("productSkn"));
dataList.add(hit.getSource());
}
brand_ProductListMap.put(lt.getKeyAsString(), dataList);
}
}
//处理品牌信息
Map<String, Object> brandInfoMap = brandMap.get(lt.getKeyAsString());
tempResult.put("info", brandInfoMap);
brand_ResultMap.put(lt.getKeyAsString(), tempResult);
}
try {
Map<String, List<Map<String, Object>>> productPricePlanMap = searchServiceHelper.searchProductPricePlan((String[]) sknStr.toArray(new String[sknStr.size()]));
brand_ResultMap.forEach((k, m) -> {
List<Map<String, Object>> productList = brand_ProductListMap.get(k);
if (productList == null) {
productList = new ArrayList<Map<String, Object>>();
}
List<Map<String, Object>> newProductList = new ArrayList<Map<String, Object>>();
for (Map<String, Object> productMap : productList) {
newProductList.add(searchServiceHelper.getProductMapWithPricePlan(productMap, productPricePlanMap));
}
m.put("product_list", newProductList);
dataMap.put(k, m);
});
} catch (Exception e) {
logger.error("[func=getGroupBrandResponseMap]" + e.getMessage(), e);
}
return dataMap;
}
@Override
public SearchApiResult aggProductsByBrandId(Map<String, String> paramMap) {
try {
logger.info("[func=aggProductsByBrandId][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、参数校验
String sortField = searchSortHelper.getLegalOrder(paramMap);
if (StringUtils.isBlank(sortField)) {
sortField = "shelveTime:desc";
}
String[] sortParts = sortField.split(":");
String realSortField = sortParts[0];
String realSortType = sortParts[1];
// 2、构造查询条件
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
searchParam.setSize(0);
// 3、获取要取的品牌商品数量
int viewNum = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
if (viewNum > 100) {
viewNum = 100;
}
// 4、构造聚合条件
List<AbstractAggregationBuilder> list = new ArrayList<AbstractAggregationBuilder>();
boolean isAscOrder = SortOrder.ASC.toString().equalsIgnoreCase(realSortType);
// 4.1)构造父聚合:品牌聚合【同时按子聚合的sort字段排序】
TermsBuilder brandAggregationBuilder = AggregationBuilders.terms("brandAgg").field("brandId").order(Terms.Order.aggregation("sort", isAscOrder)).size(viewNum);
// 4.2)添加子聚合:sort值为sortFieldName的最大值或最小值,给父聚合排序用
if (isAscOrder) {
brandAggregationBuilder.subAggregation(AggregationBuilders.min("sort").field(realSortField));
} else {
brandAggregationBuilder.subAggregation(AggregationBuilders.max("sort").field(realSortField));
}
// 4.3)添加孙聚合:按sort取一个product
brandAggregationBuilder.subAggregation(AggregationBuilders.topHits("product")
.addSort(SortBuilders.fieldSort(realSortField).order(isAscOrder ? SortOrder.ASC : SortOrder.DESC)).setSize(1));
list.add(brandAggregationBuilder);
searchParam.setAggregationBuilders(list);
// 5、构造返回结果
SearchApiResult searchApiResult = new SearchApiResult().setMessage("new-shelve list");
// 6、先从缓存中获取,如果能取到,则直接返回
JSONArray jsonArray = searchCacheService.getJSONArrayFromCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (jsonArray != null) {
CACHE_MATCH_REQUEST.info("match cache , url is :/new-shelve.json?" + HttpServletRequestUtils.genParamString(paramMap));
return searchApiResult.setData(jsonArray);
}
// 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("brandAgg")) {
return searchApiResult.setData("");
}
JSONArray productList = this.getNewShelveResponseMap(((MultiBucketsAggregation) aggMaps.get("brandAgg")));
searchCacheService.addJSONArrayToCache(indexName, searchParam, productList);
return searchApiResult.setData(productList);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_NEW_SHELVE.getEventName(), EventReportEnum.SEARCHCONTROLLER_NEW_SHELVE.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_NEW_SHELVE.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("searchNewestProductWithDiffBrand", paramMap, e);
}
}
private JSONArray getNewShelveResponseMap(final MultiBucketsAggregation aggregation) {
Iterator<? extends Bucket> itAgg = aggregation.getBuckets().iterator();
// 获取品牌聚合出来的商品
TopHits topHits;
SearchHits hits;
JSONArray result = new JSONArray();
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=getNewShelveResponseMap][Exception={}][begin={}]", e, System.currentTimeMillis());
}
return result;
}
@Override
public SearchApiResult aggProductsByBrandIdInParam(Map<String, String> paramMap) {
try {
logger.info("[func=aggProductsByBrandIdInParam][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、参数校验
if (!paramMap.containsKey("brand")) {
return new SearchApiResult().setCode(400).setMessage("没有 brand参数 ");
}
// 2、处理排序方式
String sortField = searchSortHelper.getLegalOrder(paramMap);
if (StringUtils.isBlank(sortField)) {
sortField = "shelveTime:desc";
}
String[] sortParts = sortField.split(":");
String realSortField = sortParts[0];
String realSortType = sortParts[1];
SortOrder realSortOrder = SortOrder.ASC.toString().equalsIgnoreCase(realSortType) ? SortOrder.ASC : SortOrder.DESC;
// 3、构造查询参数
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
// 4、构造聚合参数
List<AbstractAggregationBuilder> list = new ArrayList<AbstractAggregationBuilder>();
// 获取取商品的数量
// 构造品牌聚合参数[最多取100个品牌的一个商品,取回来之后再做排序]
TermsBuilder brandAggregationBuilder = AggregationBuilders.terms("brandAgg").field("brandId").size(100);
// 再构造对应HIT到的商品的聚合参数
FieldSortBuilder productSortBuilder = SortBuilders.fieldSort(realSortField).order(realSortOrder);
TopHitsBuilder productTopHitsBuilder = AggregationBuilders.topHits("product").addSort(productSortBuilder).setSize(1);
brandAggregationBuilder.subAggregation(productTopHitsBuilder);
list.add(brandAggregationBuilder);
searchParam.setAggregationBuilders(list);
// 5、设置报文缓存参数
int limit = StringUtils.isBlank(paramMap.get("limit")) ? 1 : Integer.parseInt(paramMap.get("limit"));
searchParam.setOffset(limit);// 这个参数只是用来生成报文以做缓存,不要动
searchParam.setSize(0);
// 6、构造返回结果
SearchApiResult searchApiResult = new SearchApiResult().setMessage("new product List.");
// 7、先从缓存中获取,如果能取到,则直接返回
JSONArray jsonArray = searchCacheService.getJSONArrayFromCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (jsonArray != null) {
CACHE_MATCH_REQUEST.info("match cache , url is :/new_product.json?" + HttpServletRequestUtils.genParamString(paramMap));
return searchApiResult.setData(jsonArray);
}
// 8、查询ES数据
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("brandAgg")) {
return searchApiResult.setData("");
}
// 9、构造返回数据并加入缓存
jsonArray = getNewBrandResponseMap(((MultiBucketsAggregation) aggMaps.get("brandAgg")), limit, paramMap.get("brand"), realSortField, realSortOrder);
searchCacheService.addJSONArrayToCache(indexName, searchParam, jsonArray);
return searchApiResult.setData(jsonArray);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_NEW_PRODUCT.getEventName(), EventReportEnum.SEARCHCONTROLLER_NEW_PRODUCT.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_NEW_PRODUCT.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("searchNewestProductWithDiffBrand", paramMap, e);
}
}
private JSONArray getNewBrandResponseMap(MultiBucketsAggregation aggregation, int size, String brands, final String realSortField, final SortOrder realSortOrder) {
Iterator<? extends Bucket> itAgg = aggregation.getBuckets().iterator();
// 首先获取全部品牌的商品列表
Map<String, Map<String, Object>> brandMap = new HashMap<String, Map<String, Object>>();
List<String> sknStr = new ArrayList<String>();
Map<String, Map<String, Object>> dataList = new HashMap<String, Map<String, Object>>();
while (itAgg.hasNext()) {
Bucket lt = itAgg.next();
if (lt.getAggregations().getAsMap().containsKey("product")) {
TopHits topHits = lt.getAggregations().get("product");
if (topHits != null) {
SearchHits hits = topHits.getHits();
for (SearchHit hit : hits.getHits()) {
sknStr.add("" + hit.getSource().get("productSkn"));
dataList.put(lt.getKeyAsString(), hit.getSource());
}
}
}
}
try {
Map<String, List<Map<String, Object>>> productPricePlanMap = searchServiceHelper.searchProductPricePlan((String[]) sknStr.toArray(new String[sknStr.size()]));
dataList.forEach((k, m) -> {
brandMap.put(k, searchServiceHelper.getProductMapWithPricePlan(m, productPricePlanMap));
});
} catch (Exception e) {
logger.error("[func=getNewBrandResponseMap][Exception={}][begin={}]", e, System.currentTimeMillis());
}
// 获取前面“size”个品牌的商品
if (brandMap.size() == 0) {
return new JSONArray();
}
// 购造商品列表
List<Map<String, Object>> productList = new ArrayList<Map<String, Object>>();
String[] brandIds = brands.split(",");
if (brandIds.length < size || brandMap.size() <= size) {
for (Entry<String, Map<String, Object>> entry : brandMap.entrySet()) {
productList.add(entry.getValue());
}
} else {
int num = 0;
int i = 0;
while (num < size) {
if (brandMap.containsKey(brandIds[i])) {
productList.add(brandMap.get(brandIds[i]));
num++;
}
i++;
}
}
// 再按照某个字段对商品排序
Collections.sort(productList, new Comparator<Map<String, Object>>() {
public int compare(Map<String, Object> o1, Map<String, Object> o2) {
Object realSortFieldValue1 = o1.get(realSortField);
Object realSortFieldValue2 = o1.get(realSortField);
int map1value = getIntValue(realSortFieldValue1);
int map2value = getIntValue(realSortFieldValue2);
if ("desc".equalsIgnoreCase(realSortOrder.name())) {
return map2value - map1value;
} else {
return map1value - map2value;
}
}
});
JSONArray jsonArray = new JSONArray();
jsonArray.addAll(productList);
return jsonArray;
}
private int getIntValue(Object value) {
if (value == null) {
return 0;
}
try {
return Integer.parseInt(value.toString());
} catch (Exception e) {
return 0;
}
}
}
... ...
... ... @@ -2,6 +2,7 @@ package com.yoho.search.service.servicenew.impl;
import com.alibaba.fastjson.JSONObject;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.ConvertUtils;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.core.es.model.SearchParam;
... ... @@ -105,12 +106,17 @@ public class ShopsServiceImpl extends BaseService implements IShopsService, Appl
return searchApiResult.setCode(500);
}
//5)查询shops索引,获取shopsInfo
SearchApiResult searchResultShops = getShopsInfo(paramMap);
JSONObject jsonObject = (JSONObject)searchResultShops.getData();
Map<String, Map<String, Object>> shopInfoMap = (Map<String, Map<String, Object>>)jsonObject.get("shopInfo");
// 5)、构建返回结果并将结果存进缓存
dataMap = new JSONObject();
dataMap.put("total", searchResult.getTotal());
Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
if (aggMaps.containsKey("shopAgg")) {
dataMap.put("shops", getGroupShopResponseMap(((MultiBucketsAggregation) aggMaps.get("shopAgg")), size));
dataMap.put("shops", getGroupShopResponseMap(((MultiBucketsAggregation) aggMaps.get("shopAgg")), shopInfoMap, size));
} else {
dataMap.put("shops", new JSONObject());
}
... ... @@ -284,7 +290,7 @@ public class ShopsServiceImpl extends BaseService implements IShopsService, Appl
}
}
private Map<String, Object> getGroupShopResponseMap(MultiBucketsAggregation aggregation, int size) {
private Map<String, Object> getGroupShopResponseMap(MultiBucketsAggregation aggregation, Map<String, Map<String, Object>> shopInfoMap,int size) {
Iterator<? extends Bucket> itAgg = aggregation.getBuckets().iterator();
Map<String, Object> dataMap = new HashMap<String, Object>();
Map<String, List<Map<String, Object>>> dataListMap = new HashMap<String, List<Map<String, Object>>>();
... ... @@ -309,6 +315,10 @@ public class ShopsServiceImpl extends BaseService implements IShopsService, Appl
}
}
dataMapMap.put(lt.getKeyAsString(), map);
//处理品牌信息
Map<String, Object> brandInfo = shopInfoMap.get(lt.getKeyAsString());
map.put("info", brandInfo);
dataMapMap.put(lt.getKeyAsString(), map);
}
try {
Map<String, List<Map<String, Object>>> productPricePlanMap = searchServiceHelper.searchProductPricePlan((String[]) sknStr.toArray(new String[sknStr.size()]));
... ... @@ -395,6 +405,51 @@ public class ShopsServiceImpl extends BaseService implements IShopsService, Appl
/**
* 查shop索引信息,用于group_shop接口
* @param paramMap
* @return
*/
private SearchApiResult getShopsInfo(Map<String, String> paramMap) {
try {
logger.info("[func=getShopsInfo][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、构建SearchParam
SearchParam searchParam = new SearchParam();
BoolQueryBuilder boolFilterForShops = this.constructShopsFilterBuilder(paramMap);
searchParam.setFiter(boolFilterForShops);
searchParam.setSize(10000);
searchParam.setQuery(QueryBuilders.matchAllQuery());
final String indexName = ISearchConstants.INDEX_NAME_SHOPS;
SearchApiResult searchApiResult = new SearchApiResult().setMessage("shops info");
// 2、先从缓存里取数据
JSONObject returnMap = searchCacheService.getJSONObjectFromCache(indexName, searchParam);
if (returnMap != null) {
CACHE_MATCH_REQUEST.info("match cache , url is :/shops.json?" + HttpServletRequestUtils.genParamString(paramMap));
return searchApiResult.setData(returnMap);
}
// 3、根据searchParam查询ES
returnMap = new JSONObject();
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_SHOPS, searchParam);
List<String> shopIds = new ArrayList<String>();
Map<String, Map<String, Object>> shopInfoMap = new HashMap<String, Map<String, Object>>();
if (searchResult != null && searchResult.getResultList() != null && !searchResult.getResultList().isEmpty()) {
List<Map<String, Object>> result = searchResult.getResultList();
for (int i = 0; i < result.size(); i++) {
Map<String, Object> shopInfo = result.get(i);
String shopId = shopInfo.get("shopsId").toString();
shopInfoMap.put(shopId, shopInfo);
shopIds.add(shopId);
}
}
returnMap.put("shopInfo",shopInfoMap);
searchCacheService.addJSONObjectToCache(indexName, searchParam, returnMap);
return searchApiResult.setData(returnMap);
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult("searchShopsNew", paramMap, e);
}
}
/**
* 配置Filter
*
* @param paramMap
... ... @@ -403,6 +458,10 @@ public class ShopsServiceImpl extends BaseService implements IShopsService, Appl
*/
private BoolQueryBuilder constructShopsFilterBuilder(Map<String, String> paramMap) throws Exception {
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_SHOP) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_SHOP))) {
int[] shopsIds = ConvertUtils.stringToIntArray(paramMap.get(SearchRequestParams.PARAM_SEARCH_SHOP), ",");
boolFilter.must(QueryBuilders.termsQuery("shopsId", shopsIds));
}
boolFilter = BoolQueryTermQuery(paramMap, boolFilter, SearchRequestParams.SHOPS_PARAM_BLKSTATUS);
boolFilter = BoolQueryTermQuery(paramMap, boolFilter, SearchRequestParams.SHOPS_PARAM_CHECKSTATUS);
boolFilter = BoolQueryTermQuery(paramMap, boolFilter, SearchRequestParams.SHOPS_PARAM_EXAMINESTATUS);
... ...