Authored by hugufei

优化new_product接口,去除ProductListHelper中无用的类

@@ -102,34 +102,6 @@ public class ProductListHelper { @@ -102,34 +102,6 @@ public class ProductListHelper {
102 /** 102 /**
103 * 从es返回的列表,生成返回列表 103 * 从es返回的列表,生成返回列表
104 */ 104 */
105 - public Map<String, Map<String, Object>> buildReturnInfoByEsSourceMap(Map<String, Map<String, Object>> productEsSourceMap) {  
106 - //1、获取全部的productEsSource  
107 - List<Map<String, Object>> productEsSourceList = new ArrayList<>();  
108 - for (Map<String, Object> productEsSource : productEsSourceMap.values()) {  
109 - productEsSourceList.add(productEsSource);  
110 - }  
111 - //2、填充数据并按skn转成map  
112 - List<Map<String, Object>> productReturnInfoList = this.buildReturnInfoByEsSourceList(productEsSourceList);  
113 - Map<String, Map<String, Object>> productReturnInfoMap = new HashMap<>();  
114 - for (Map<String, Object> productReturnInfo : productReturnInfoList) {  
115 - productReturnInfoMap.put(MapUtils.getString(productReturnInfo, "product_skn", "0"), productReturnInfo);  
116 - }  
117 - //3、生成结果map  
118 - Map<String, Map<String, Object>> results = new HashMap<>();  
119 - for (Map.Entry<String, Map<String, Object>> entry : productEsSourceMap.entrySet()) {  
120 - Map<String, Object> productEsSource = entry.getValue();  
121 - String productSkn = MapUtils.getString(productEsSource, ProductIndexEsField.productSkn, "0");  
122 - if (productReturnInfoMap.containsKey(productSkn)) {  
123 - results.put(entry.getKey(), productReturnInfoMap.get(productSkn));  
124 - }  
125 - }  
126 - return results;  
127 - }  
128 -  
129 -  
130 - /**  
131 - * 从es返回的列表,生成返回列表  
132 - */  
133 public Map<String, List<Map<String, Object>>> buildReturnInfoByEsSourceListMap(Map<String, List<Map<String, Object>>> productEsSourceListMap) { 105 public Map<String, List<Map<String, Object>>> buildReturnInfoByEsSourceListMap(Map<String, List<Map<String, Object>>> productEsSourceListMap) {
134 //1、获取全部的productEsSource 106 //1、获取全部的productEsSource
135 List<Map<String, Object>> productEsSourceList = new ArrayList<>(); 107 List<Map<String, Object>> productEsSourceList = new ArrayList<>();
@@ -11,7 +11,9 @@ import java.util.List; @@ -11,7 +11,9 @@ import java.util.List;
11 import java.util.Map; 11 import java.util.Map;
12 import java.util.Map.Entry; 12 import java.util.Map.Entry;
13 13
  14 +import com.yoho.search.base.utils.ConvertUtils;
14 import com.yoho.search.service.helper.ProductListHelper; 15 import com.yoho.search.service.helper.ProductListHelper;
  16 +import org.apache.commons.collections.MapUtils;
15 import org.apache.commons.lang.StringUtils; 17 import org.apache.commons.lang.StringUtils;
16 import org.elasticsearch.index.query.BoolQueryBuilder; 18 import org.elasticsearch.index.query.BoolQueryBuilder;
17 import org.elasticsearch.index.query.QueryBuilders; 19 import org.elasticsearch.index.query.QueryBuilders;
@@ -65,397 +67,377 @@ import com.yoho.search.service.service.IBrandService; @@ -65,397 +67,377 @@ import com.yoho.search.service.service.IBrandService;
65 @Service 67 @Service
66 public class BrandServiceImpl extends AbstractCacheAbleService implements IBrandService, ApplicationEventPublisherAware { 68 public class BrandServiceImpl extends AbstractCacheAbleService implements IBrandService, ApplicationEventPublisherAware {
67 69
68 - private static final Logger logger = LoggerFactory.getLogger(BrandServiceImpl.class);  
69 -  
70 - @Autowired  
71 - private SearchSortHelper searchSortHelper;  
72 - @Autowired  
73 - private SearchParamHelper searchParamHelper;  
74 - @Autowired  
75 - private AggregationService aggregationService;  
76 - @Autowired  
77 - private SearchCommonService searchCommonService;  
78 - @Autowired  
79 - private BrandIndexBaseService brandIndexBaseService;  
80 - @Autowired  
81 - private ProductIndexBaseService productIndexBaseService;  
82 - @Autowired  
83 - private AggregationFactoryService aggregationFactoryService;  
84 - @Autowired  
85 - private SearchCommonHelper searchCommonHelper;  
86 - @Autowired  
87 - private ProductListHelper productListHelper;  
88 -  
89 - @Override  
90 - public SearchCache getSearchCache() {  
91 - return searchCacheFactory.getBrandRelatedCache();  
92 - }  
93 -  
94 - private ApplicationEventPublisher publisher;  
95 -  
96 - @Override  
97 - public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {  
98 - this.publisher = applicationEventPublisher;  
99 - }  
100 -  
101 - @Override  
102 - public SearchApiResult aggBrand(Map<String, String> paramMap) {  
103 - try {  
104 - logger.info("[func=aggBrand][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());  
105 - return this.aggBrand(paramMap, null);  
106 - } catch (Exception e) {  
107 - return SearchApiResultUtils.errorSearchApiResult("aggBrand", paramMap, e);  
108 - }  
109 - }  
110 -  
111 - @Override  
112 - public SearchApiResult aggBrand(Map<String, String> paramMap, BoolQueryBuilder mustFilter) {  
113 - try {  
114 - // 1、构造带filter和query的SearchParam  
115 - boolean needPreAggregation = "Y".equals(paramMap.getOrDefault(SearchRequestParams.PARAM_SEARCH_AGG_WITH_PARAM_BRAND, "N")) ? false : true;  
116 - SearchParam searchParam = searchParamHelper.buildSearchParam(paramMap, false, mustFilter, needPreAggregation ? "brand" : null);  
117 -  
118 - // 2、构造aggrations  
119 - IAggregation brandAggregation = aggregationFactoryService.getBrandAggregation(paramMap);  
120 - searchParam.setAggregationBuilders(Arrays.asList(brandAggregation.getBuilder()));  
121 -  
122 - // 3、从缓存中获取  
123 - final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;  
124 - JSONArray cacheJSONArray = searchCacheService.getJSONArrayFromCache(this.searchCache, indexName, searchParam);  
125 - if (cacheJSONArray != null) {  
126 - SearchCacheMatchLogger.doSearchCacheMatchLog("/productindex/aggBrand.json", paramMap);  
127 - return new SearchApiResult().setData(cacheJSONArray);  
128 - }  
129 - // 4、从ES中获取  
130 - JSONObject jsonObject = aggregationService.getAggNameAndResponse(brandAggregation, searchParam);  
131 - if (jsonObject == null) {  
132 - return new SearchApiResult().setData(500).setMessage("exception");  
133 - }  
134 - // 5、生成结果并且加入缓存  
135 - JSONArray brandJSONArray = jsonObject.getJSONArray(brandAggregation.aggName());  
136 - if (brandJSONArray != null) {  
137 - searchCacheService.addJSONArrayToCache(this.searchCache, indexName, searchParam, brandJSONArray);  
138 - }  
139 - return new SearchApiResult().setData(brandJSONArray);  
140 - } catch (Exception e) {  
141 - return SearchApiResultUtils.errorSearchApiResult("aggBrand", paramMap, e);  
142 - }  
143 - }  
144 -  
145 - @Override  
146 - public SearchApiResult brands(Map<String, String> paramMap) {  
147 - try {  
148 - logger.info("[func=brands][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());  
149 - // 1、构造查询参数  
150 - SearchParam searchParam = searchParamHelper.buildDefault(paramMap);  
151 -  
152 - // 2、构造聚合参数  
153 - List<AbstractAggregationBuilder<?>> list = new ArrayList<AbstractAggregationBuilder<?>>();  
154 - list.add(AggregationBuilders.terms("brandAlifAgg").field(ProductIndexEsField.brandAlif).size(1000).order(Terms.Order.term(true))  
155 - .subAggregation(AggregationBuilders.terms("brandAgg").field(ProductIndexEsField.brandId).size(1000)));  
156 - searchParam.setAggregationBuilders(list);  
157 - searchParam.setSize(0);  
158 -  
159 - // 3、brand数据量比较大,走本地缓存  
160 - final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;  
161 - JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, indexName, searchParam);  
162 - if (cacheObject != null) {  
163 - SearchCacheMatchLogger.doSearchCacheMatchLog("/productindex/brands.json", paramMap);  
164 - return new SearchApiResult().setData(cacheObject);  
165 - }  
166 - // 4、查询ES  
167 - SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);  
168 - SearchApiResult searchApiResult = new SearchApiResult().setMessage("brand List.");  
169 - if (searchResult == null || searchResult.getAggMaps() == null) {  
170 - return searchApiResult.setCode(500);  
171 - }  
172 - Map<String, Aggregation> aggregationResult = searchResult.getAggMaps();  
173 - if (!aggregationResult.containsKey("brandAlifAgg")) {  
174 - return searchApiResult;  
175 - }  
176 - // 5、构造返回结果并加入缓存  
177 - JSONObject result = new JSONObject();  
178 - result.put("brands", makeBrandResponse(((MultiBucketsAggregation) aggregationResult.get("brandAlifAgg"))));  
179 - searchCacheService.addJSONObjectToCache(this.searchCache, indexName, searchParam, result);  
180 - return searchApiResult.setData(result);  
181 - } catch (Exception e) {  
182 - publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_BRANDS.getEventName(), EventReportEnum.SEARCHCONTROLLER_BRANDS.getFunctionName(),  
183 - EventReportEnum.SEARCHCONTROLLER_BRANDS.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));  
184 - return SearchApiResultUtils.errorSearchApiResult("brands", paramMap, e);  
185 - }  
186 - }  
187 -  
188 - /**  
189 - * 制作品牌报文  
190 - */  
191 - private Map<String, JSONArray> makeBrandResponse(MultiBucketsAggregation aggregation) {  
192 - // 1)获取每个brandAlif对应的brandIds  
193 - Map<String, List<String>> brandAlif2BrandIds = new LinkedHashMap<String, List<String>>();  
194 - for (Bucket brandAlifBucket : aggregation.getBuckets()) {  
195 - String brandAlif = brandAlifBucket.getKeyAsString();  
196 - List<String> brandIds = new ArrayList<String>();  
197 - MultiBucketsAggregation brandAggs = (MultiBucketsAggregation) brandAlifBucket.getAggregations().asMap().get("brandAgg");  
198 - for (Bucket brandIdBucket : brandAggs.getBuckets()) {  
199 - brandIds.addAll(Arrays.asList(brandIdBucket.getKeyAsString().split(",")));  
200 - }  
201 - brandAlif2BrandIds.put(brandAlif, brandIds);  
202 - }  
203 - // 2)获取所有的品牌id  
204 - List<String> brandIds = new ArrayList<String>();  
205 - for (Map.Entry<String, List<String>> entry : brandAlif2BrandIds.entrySet()) {  
206 - brandIds.addAll(entry.getValue());  
207 - }  
208 - // 3)获取所有的品牌数据  
209 - List<Map<String, Object>> brandList = brandIndexBaseService.getBrandListByIds(brandIds);  
210 - Map<String, Map<String, Object>> brandIdMap = new HashMap<String, Map<String, Object>>();  
211 - for (Map<String, Object> brand : brandList) {  
212 - brandIdMap.put(brand.getOrDefault("id", 0).toString(), brand);  
213 - }  
214 - // 4)构造真正的数据  
215 - Map<String, JSONArray> result = new LinkedHashMap<String, JSONArray>();  
216 - for (Map.Entry<String, List<String>> entry : brandAlif2BrandIds.entrySet()) {  
217 - String brandAlif = entry.getKey();  
218 - JSONArray brands = new JSONArray();  
219 - for (String brandId : entry.getValue()) {  
220 - Map<String, Object> brand = brandIdMap.get(brandId);  
221 - if (brand != null) {  
222 - brands.add(brand);  
223 - }  
224 - }  
225 - result.put(brandAlif, brands);  
226 - }  
227 - return result;  
228 - }  
229 -  
230 - @Override  
231 - public SearchApiResult brandList(Map<String, String> paramMap) {  
232 - try {  
233 - logger.info("[func=brandList][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());  
234 -  
235 - // 1)构建参数  
236 - SearchParam searchParam = new SearchParam();  
237 - searchParam.setSize(10000);  
238 - searchParam.setQuery(QueryBuilders.matchAllQuery());  
239 - BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();  
240 - boolQueryBuilder.mustNot(QueryBuilders.termQuery("isGlobal", "Y"));  
241 - searchParam.setFiter(boolQueryBuilder);  
242 -  
243 - // 2、brand数据量比较大,走本地缓存。guavacache缓存中获取result,没有到es中获取  
244 - final String brandIndexName = ISearchConstants.INDEX_NAME_BRAND;  
245 - JSONArray cacheJSONArray = searchCacheService.getJSONArrayFromCache(this.searchCache, brandIndexName, searchParam);  
246 - if (cacheJSONArray != null) {  
247 - SearchCacheMatchLogger.doSearchCacheMatchLog("/brand/list.json", paramMap);  
248 - return new SearchApiResult().setData(cacheJSONArray);  
249 - }  
250 - // 3、执行搜索  
251 - SearchResult searchResult = searchCommonService.doSearch(brandIndexName, searchParam);  
252 - if (searchResult == null || searchResult.getResultList().isEmpty()) {  
253 - return new SearchApiResult().setData(400).setMessage("empty result");  
254 - }  
255 - // 4、构建返回结果并加入缓存  
256 - List<Map<String, Object>> result = searchResult.getResultList();  
257 - JSONArray jsonArray = new JSONArray();  
258 - for (Map<String, Object> map : result) {  
259 - Map<String, Object> brandInfo = brandIndexBaseService.getBrandMap(map);  
260 - jsonArray.add(brandInfo);  
261 - }  
262 - searchCacheService.addJSONArrayToCache(this.searchCache, brandIndexName, searchParam, jsonArray);  
263 - return new SearchApiResult().setMessage("brands info").setData(jsonArray);  
264 - } catch (Exception e) {  
265 - publisher.publishEvent(new SearchEvent(EventReportEnum.BRANDCONTROLLER_BRAND_LIST.getEventName(), EventReportEnum.BRANDCONTROLLER_BRAND_LIST.getFunctionName(),  
266 - EventReportEnum.BRANDCONTROLLER_BRAND_LIST.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));  
267 - return SearchApiResultUtils.errorSearchApiResult("brandList", paramMap, e);  
268 - }  
269 - }  
270 -  
271 - @Override  
272 - public SearchApiResult groupBrands(Map<String, String> paramMap) {  
273 - try {  
274 - logger.info("[func=groupBrands][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());  
275 - // 1、参数检验  
276 - if (!paramMap.containsKey("brand")) {  
277 - return new SearchApiResult().setCode(400).setMessage("没有 brand参数 ");  
278 - }  
279 - // 2、获取聚合条件  
280 - int topHitCount = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));  
281 - // 3、是否需要个性化  
282 - String topHitOrder = "heatValue:desc";  
283 - if (topHitCount > 0 && searchCommonHelper.isNeedPersonalSearch(paramMap)) {  
284 - topHitOrder = "_score:desc";  
285 - }  
286 -  
287 - // 4、构建searchParam  
288 - SearchParam searchParam = searchParamHelper.buildWithPersional(paramMap, topHitCount > 0 ? true : false);  
289 - IAggregation groupBrandAgg = aggregationFactoryService.getGroupBrandAggregation(topHitOrder, topHitCount);  
290 - searchParam.setAggregationBuilders(Arrays.asList(groupBrandAgg.getBuilder()));  
291 - searchParam.setSize(0);  
292 - searchParam.setOffset(topHitCount * 2);// justForCache  
293 -  
294 - // 5、从缓存中获取  
295 - final String productIndexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;  
296 - JSONObject groupBrandResult = searchCacheService.getJSONObjectFromCache(this.searchCache, productIndexName, searchParam);  
297 - if (groupBrandResult != null) {  
298 - SearchCacheMatchLogger.doSearchCacheMatchLog("/productindex/groupBrands.json", paramMap);  
299 - return new SearchApiResult().setData(groupBrandResult);  
300 - }  
301 - // 6、从ES中获取  
302 - groupBrandResult = aggregationService.getAggNameAndResponseWithTotal(groupBrandAgg, searchParam);  
303 - if (groupBrandResult == null) {  
304 - return new SearchApiResult().setData(500).setMessage("exception");  
305 - }  
306 - // 7、生成结果并且加入缓存  
307 - JSONObject realResult = new JSONObject();  
308 - realResult.put("total", groupBrandResult.getOrDefault("total", 0));  
309 - realResult.put("brands", groupBrandResult.getOrDefault(groupBrandAgg.aggName(), new JSONObject()));  
310 - searchCacheService.addJSONObjectToCache(this.searchCache, productIndexName, searchParam, realResult);  
311 - return new SearchApiResult().setData(realResult).setMessage("groupBrands new List.");  
312 - } catch (Exception e) {  
313 - publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_GROUP_BRANDS.getEventName(), EventReportEnum.SEARCHCONTROLLER_GROUP_BRANDS.getFunctionName(),  
314 - EventReportEnum.SEARCHCONTROLLER_GROUP_BRANDS.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));  
315 - return SearchApiResultUtils.errorSearchApiResult("groupBrands", paramMap, e);  
316 - }  
317 - }  
318 -  
319 -  
320 - @Override  
321 - public SearchApiResult aggProductsByBrandIdInParam(Map<String, String> paramMap) {  
322 - try {  
323 - logger.info("[func=aggProductsByBrandIdInParam][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());  
324 -  
325 - // 1、参数校验  
326 - if (!paramMap.containsKey("brand")) {  
327 - return new SearchApiResult().setCode(400).setMessage("没有 brand参数 ");  
328 - }  
329 - // 2、处理排序方式  
330 - String sortField = searchSortHelper.getLegalOrder(paramMap);  
331 - if (StringUtils.isBlank(sortField)) {  
332 - sortField = "shelveTime:desc";  
333 - }  
334 - String[] sortParts = sortField.split(":");  
335 - String realSortField = sortParts[0];  
336 - String realSortType = sortParts[1];  
337 - SortOrder realSortOrder = SortOrder.ASC.toString().equalsIgnoreCase(realSortType) ? SortOrder.ASC : SortOrder.DESC;  
338 -  
339 - // 3、构造查询参数  
340 - SearchParam searchParam = searchParamHelper.buildDefault(paramMap);  
341 -  
342 - // 4、构造聚合参数  
343 - List<AbstractAggregationBuilder<?>> list = new ArrayList<AbstractAggregationBuilder<?>>();  
344 - // 获取取商品的数量  
345 - // 构造品牌聚合参数[最多取100个品牌的一个商品,取回来之后再做排序]  
346 - TermsAggregationBuilder brandAggregationBuilder = AggregationBuilders.terms("brandAgg").field(ProductIndexEsField.brandId).size(100);  
347 - // 再构造对应HIT到的商品的聚合参数  
348 - FieldSortBuilder productSortBuilder = SortBuilders.fieldSort(realSortField).order(realSortOrder);  
349 - TopHitsAggregationBuilder productTopHitsBuilder = AggregationBuilders.topHits("product").sort(productSortBuilder).size(1);  
350 - brandAggregationBuilder.subAggregation(productTopHitsBuilder);  
351 - list.add(brandAggregationBuilder);  
352 - searchParam.setAggregationBuilders(list);  
353 -  
354 - // 5、设置报文缓存参数  
355 - int limit = StringUtils.isBlank(paramMap.get("limit")) ? 1 : Integer.parseInt(paramMap.get("limit"));  
356 - searchParam.setOffset(limit);// 这个参数只是用来生成报文以做缓存,不要动  
357 - searchParam.setSize(0);  
358 -  
359 - // 6、构造返回结果  
360 - SearchApiResult searchApiResult = new SearchApiResult().setMessage("new product List.");  
361 -  
362 - // 7、先从缓存中获取,如果能取到,则直接返回  
363 - JSONArray jsonArray = searchCacheService.getJSONArrayFromCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);  
364 - if (jsonArray != null) {  
365 - SearchCacheMatchLogger.doSearchCacheMatchLog("/new_product.json", paramMap);  
366 - return searchApiResult.setData(jsonArray);  
367 - }  
368 -  
369 - // 8、查询ES数据  
370 - final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;  
371 - SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);  
372 - if (searchResult == null || searchResult.getAggMaps() == null) {  
373 - return searchApiResult.setData("");  
374 - }  
375 - Map<String, Aggregation> aggMaps = searchResult.getAggMaps();  
376 - if (!aggMaps.containsKey("brandAgg")) {  
377 - return searchApiResult.setData("");  
378 - }  
379 -  
380 - // 9、构造返回数据并加入缓存  
381 - jsonArray = getNewBrandResponseMap(((MultiBucketsAggregation) aggMaps.get("brandAgg")), limit, paramMap.get("brand"), realSortField, realSortOrder);  
382 - searchCacheService.addJSONArrayToCache(this.searchCache, indexName, searchParam, jsonArray);  
383 - return searchApiResult.setData(jsonArray);  
384 - } catch (Exception e) {  
385 - publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_NEW_PRODUCT.getEventName(), EventReportEnum.SEARCHCONTROLLER_NEW_PRODUCT.getFunctionName(),  
386 - EventReportEnum.SEARCHCONTROLLER_NEW_PRODUCT.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));  
387 - return SearchApiResultUtils.errorSearchApiResult("searchNewestProductWithDiffBrand", paramMap, e);  
388 - }  
389 - }  
390 -  
391 - private JSONArray getNewBrandResponseMap(MultiBucketsAggregation aggregation, int size, String brands, final String realSortField, final SortOrder realSortOrder) {  
392 - Iterator<? extends Bucket> itAgg = aggregation.getBuckets().iterator();  
393 - // 首先获取全部品牌的商品列表  
394 - Map<String, Map<String, Object>> brand_product_map = new HashMap<>();  
395 - while (itAgg.hasNext()) {  
396 - Bucket lt = itAgg.next();  
397 - if (lt.getAggregations().getAsMap().containsKey("product")) {  
398 - TopHits topHits = lt.getAggregations().get("product");  
399 - if (topHits != null) {  
400 - SearchHits hits = topHits.getHits();  
401 - for (SearchHit hit : hits.getHits()) {  
402 - brand_product_map.put(lt.getKeyAsString(), hit.getSource());  
403 - }  
404 - }  
405 - }  
406 - }  
407 - brand_product_map = productListHelper.buildReturnInfoByEsSourceMap(brand_product_map);  
408 -  
409 - // 获取前面“size”个品牌的商品  
410 - if (brand_product_map.size() == 0) {  
411 - return new JSONArray();  
412 - }  
413 - // 购造商品列表  
414 - List<Map<String, Object>> productList = new ArrayList<Map<String, Object>>();  
415 - String[] brandIds = brands.split(",");  
416 - if (brandIds.length < size || brand_product_map.size() <= size) {  
417 - for (Entry<String, Map<String, Object>> entry : brand_product_map.entrySet()) {  
418 - productList.add(entry.getValue());  
419 - }  
420 - } else {  
421 - int num = 0;  
422 - int i = 0;  
423 - while (num < size) {  
424 - if (brand_product_map.containsKey(brandIds[i])) {  
425 - productList.add(brand_product_map.get(brandIds[i]));  
426 - num++;  
427 - }  
428 - i++;  
429 - }  
430 - }  
431 - // 再按照某个字段对商品排序  
432 - Collections.sort(productList, new Comparator<Map<String, Object>>() {  
433 - public int compare(Map<String, Object> o1, Map<String, Object> o2) {  
434 - Object realSortFieldValue1 = o1.get(realSortField);  
435 - Object realSortFieldValue2 = o1.get(realSortField);  
436 - int map1value = getIntValue(realSortFieldValue1);  
437 - int map2value = getIntValue(realSortFieldValue2);  
438 - if ("desc".equalsIgnoreCase(realSortOrder.name())) {  
439 - return map2value - map1value;  
440 - } else {  
441 - return map1value - map2value;  
442 - }  
443 - }  
444 - });  
445 - JSONArray jsonArray = new JSONArray();  
446 - jsonArray.addAll(productList);  
447 - return jsonArray;  
448 - }  
449 -  
450 - private int getIntValue(Object value) {  
451 - if (value == null) {  
452 - return 0;  
453 - }  
454 - try {  
455 - return Integer.parseInt(value.toString());  
456 - } catch (Exception e) {  
457 - return 0;  
458 - }  
459 - }  
460 - 70 + private static final Logger logger = LoggerFactory.getLogger(BrandServiceImpl.class);
  71 +
  72 + @Autowired
  73 + private SearchSortHelper searchSortHelper;
  74 + @Autowired
  75 + private SearchParamHelper searchParamHelper;
  76 + @Autowired
  77 + private AggregationService aggregationService;
  78 + @Autowired
  79 + private SearchCommonService searchCommonService;
  80 + @Autowired
  81 + private BrandIndexBaseService brandIndexBaseService;
  82 + @Autowired
  83 + private AggregationFactoryService aggregationFactoryService;
  84 + @Autowired
  85 + private SearchCommonHelper searchCommonHelper;
  86 + @Autowired
  87 + private ProductListHelper productListHelper;
  88 +
  89 + @Override
  90 + public SearchCache getSearchCache() {
  91 + return searchCacheFactory.getBrandRelatedCache();
  92 + }
  93 +
  94 + private ApplicationEventPublisher publisher;
  95 +
  96 + @Override
  97 + public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
  98 + this.publisher = applicationEventPublisher;
  99 + }
  100 +
  101 + @Override
  102 + public SearchApiResult aggBrand(Map<String, String> paramMap) {
  103 + try {
  104 + logger.info("[func=aggBrand][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
  105 + return this.aggBrand(paramMap, null);
  106 + } catch (Exception e) {
  107 + return SearchApiResultUtils.errorSearchApiResult("aggBrand", paramMap, e);
  108 + }
  109 + }
  110 +
  111 + @Override
  112 + public SearchApiResult aggBrand(Map<String, String> paramMap, BoolQueryBuilder mustFilter) {
  113 + try {
  114 + // 1、构造带filter和query的SearchParam
  115 + boolean needPreAggregation = "Y".equals(paramMap.getOrDefault(SearchRequestParams.PARAM_SEARCH_AGG_WITH_PARAM_BRAND, "N")) ? false : true;
  116 + SearchParam searchParam = searchParamHelper.buildSearchParam(paramMap, false, mustFilter, needPreAggregation ? "brand" : null);
  117 +
  118 + // 2、构造aggrations
  119 + IAggregation brandAggregation = aggregationFactoryService.getBrandAggregation(paramMap);
  120 + searchParam.setAggregationBuilders(Arrays.asList(brandAggregation.getBuilder()));
  121 +
  122 + // 3、从缓存中获取
  123 + final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
  124 + JSONArray cacheJSONArray = searchCacheService.getJSONArrayFromCache(this.searchCache, indexName, searchParam);
  125 + if (cacheJSONArray != null) {
  126 + SearchCacheMatchLogger.doSearchCacheMatchLog("/productindex/aggBrand.json", paramMap);
  127 + return new SearchApiResult().setData(cacheJSONArray);
  128 + }
  129 + // 4、从ES中获取
  130 + JSONObject jsonObject = aggregationService.getAggNameAndResponse(brandAggregation, searchParam);
  131 + if (jsonObject == null) {
  132 + return new SearchApiResult().setData(500).setMessage("exception");
  133 + }
  134 + // 5、生成结果并且加入缓存
  135 + JSONArray brandJSONArray = jsonObject.getJSONArray(brandAggregation.aggName());
  136 + if (brandJSONArray != null) {
  137 + searchCacheService.addJSONArrayToCache(this.searchCache, indexName, searchParam, brandJSONArray);
  138 + }
  139 + return new SearchApiResult().setData(brandJSONArray);
  140 + } catch (Exception e) {
  141 + return SearchApiResultUtils.errorSearchApiResult("aggBrand", paramMap, e);
  142 + }
  143 + }
  144 +
  145 + @Override
  146 + public SearchApiResult brands(Map<String, String> paramMap) {
  147 + try {
  148 + logger.info("[func=brands][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
  149 + // 1、构造查询参数
  150 + SearchParam searchParam = searchParamHelper.buildDefault(paramMap);
  151 +
  152 + // 2、构造聚合参数
  153 + List<AbstractAggregationBuilder<?>> list = new ArrayList<AbstractAggregationBuilder<?>>();
  154 + list.add(AggregationBuilders.terms("brandAlifAgg").field(ProductIndexEsField.brandAlif).size(1000).order(Terms.Order.term(true))
  155 + .subAggregation(AggregationBuilders.terms("brandAgg").field(ProductIndexEsField.brandId).size(1000)));
  156 + searchParam.setAggregationBuilders(list);
  157 + searchParam.setSize(0);
  158 +
  159 + // 3、brand数据量比较大,走本地缓存
  160 + final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
  161 + JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(this.searchCache, indexName, searchParam);
  162 + if (cacheObject != null) {
  163 + SearchCacheMatchLogger.doSearchCacheMatchLog("/productindex/brands.json", paramMap);
  164 + return new SearchApiResult().setData(cacheObject);
  165 + }
  166 + // 4、查询ES
  167 + SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
  168 + SearchApiResult searchApiResult = new SearchApiResult().setMessage("brand List.");
  169 + if (searchResult == null || searchResult.getAggMaps() == null) {
  170 + return searchApiResult.setCode(500);
  171 + }
  172 + Map<String, Aggregation> aggregationResult = searchResult.getAggMaps();
  173 + if (!aggregationResult.containsKey("brandAlifAgg")) {
  174 + return searchApiResult;
  175 + }
  176 + // 5、构造返回结果并加入缓存
  177 + JSONObject result = new JSONObject();
  178 + result.put("brands", makeBrandResponse(((MultiBucketsAggregation) aggregationResult.get("brandAlifAgg"))));
  179 + searchCacheService.addJSONObjectToCache(this.searchCache, indexName, searchParam, result);
  180 + return searchApiResult.setData(result);
  181 + } catch (Exception e) {
  182 + publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_BRANDS.getEventName(), EventReportEnum.SEARCHCONTROLLER_BRANDS.getFunctionName(),
  183 + EventReportEnum.SEARCHCONTROLLER_BRANDS.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
  184 + return SearchApiResultUtils.errorSearchApiResult("brands", paramMap, e);
  185 + }
  186 + }
  187 +
  188 + /**
  189 + * 制作品牌报文
  190 + */
  191 + private Map<String, JSONArray> makeBrandResponse(MultiBucketsAggregation aggregation) {
  192 + // 1)获取每个brandAlif对应的brandIds
  193 + Map<String, List<String>> brandAlif2BrandIds = new LinkedHashMap<String, List<String>>();
  194 + for (Bucket brandAlifBucket : aggregation.getBuckets()) {
  195 + String brandAlif = brandAlifBucket.getKeyAsString();
  196 + List<String> brandIds = new ArrayList<String>();
  197 + MultiBucketsAggregation brandAggs = (MultiBucketsAggregation) brandAlifBucket.getAggregations().asMap().get("brandAgg");
  198 + for (Bucket brandIdBucket : brandAggs.getBuckets()) {
  199 + brandIds.addAll(Arrays.asList(brandIdBucket.getKeyAsString().split(",")));
  200 + }
  201 + brandAlif2BrandIds.put(brandAlif, brandIds);
  202 + }
  203 + // 2)获取所有的品牌id
  204 + List<String> brandIds = new ArrayList<String>();
  205 + for (Map.Entry<String, List<String>> entry : brandAlif2BrandIds.entrySet()) {
  206 + brandIds.addAll(entry.getValue());
  207 + }
  208 + // 3)获取所有的品牌数据
  209 + List<Map<String, Object>> brandList = brandIndexBaseService.getBrandListByIds(brandIds);
  210 + Map<String, Map<String, Object>> brandIdMap = new HashMap<String, Map<String, Object>>();
  211 + for (Map<String, Object> brand : brandList) {
  212 + brandIdMap.put(brand.getOrDefault("id", 0).toString(), brand);
  213 + }
  214 + // 4)构造真正的数据
  215 + Map<String, JSONArray> result = new LinkedHashMap<String, JSONArray>();
  216 + for (Map.Entry<String, List<String>> entry : brandAlif2BrandIds.entrySet()) {
  217 + String brandAlif = entry.getKey();
  218 + JSONArray brands = new JSONArray();
  219 + for (String brandId : entry.getValue()) {
  220 + Map<String, Object> brand = brandIdMap.get(brandId);
  221 + if (brand != null) {
  222 + brands.add(brand);
  223 + }
  224 + }
  225 + result.put(brandAlif, brands);
  226 + }
  227 + return result;
  228 + }
  229 +
  230 + @Override
  231 + public SearchApiResult brandList(Map<String, String> paramMap) {
  232 + try {
  233 + logger.info("[func=brandList][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
  234 +
  235 + // 1)构建参数
  236 + SearchParam searchParam = new SearchParam();
  237 + searchParam.setSize(10000);
  238 + searchParam.setQuery(QueryBuilders.matchAllQuery());
  239 + BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
  240 + boolQueryBuilder.mustNot(QueryBuilders.termQuery("isGlobal", "Y"));
  241 + searchParam.setFiter(boolQueryBuilder);
  242 +
  243 + // 2、brand数据量比较大,走本地缓存。guavacache缓存中获取result,没有到es中获取
  244 + final String brandIndexName = ISearchConstants.INDEX_NAME_BRAND;
  245 + JSONArray cacheJSONArray = searchCacheService.getJSONArrayFromCache(this.searchCache, brandIndexName, searchParam);
  246 + if (cacheJSONArray != null) {
  247 + SearchCacheMatchLogger.doSearchCacheMatchLog("/brand/list.json", paramMap);
  248 + return new SearchApiResult().setData(cacheJSONArray);
  249 + }
  250 + // 3、执行搜索
  251 + SearchResult searchResult = searchCommonService.doSearch(brandIndexName, searchParam);
  252 + if (searchResult == null || searchResult.getResultList().isEmpty()) {
  253 + return new SearchApiResult().setData(400).setMessage("empty result");
  254 + }
  255 + // 4、构建返回结果并加入缓存
  256 + List<Map<String, Object>> result = searchResult.getResultList();
  257 + JSONArray jsonArray = new JSONArray();
  258 + for (Map<String, Object> map : result) {
  259 + Map<String, Object> brandInfo = brandIndexBaseService.getBrandMap(map);
  260 + jsonArray.add(brandInfo);
  261 + }
  262 + searchCacheService.addJSONArrayToCache(this.searchCache, brandIndexName, searchParam, jsonArray);
  263 + return new SearchApiResult().setMessage("brands info").setData(jsonArray);
  264 + } catch (Exception e) {
  265 + publisher.publishEvent(new SearchEvent(EventReportEnum.BRANDCONTROLLER_BRAND_LIST.getEventName(), EventReportEnum.BRANDCONTROLLER_BRAND_LIST.getFunctionName(),
  266 + EventReportEnum.BRANDCONTROLLER_BRAND_LIST.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
  267 + return SearchApiResultUtils.errorSearchApiResult("brandList", paramMap, e);
  268 + }
  269 + }
  270 +
  271 + @Override
  272 + public SearchApiResult groupBrands(Map<String, String> paramMap) {
  273 + try {
  274 + logger.info("[func=groupBrands][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
  275 + // 1、参数检验
  276 + if (!paramMap.containsKey("brand")) {
  277 + return new SearchApiResult().setCode(400).setMessage("没有 brand参数 ");
  278 + }
  279 + // 2、获取聚合条件
  280 + int topHitCount = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
  281 + // 3、是否需要个性化
  282 + String topHitOrder = "heatValue:desc";
  283 + if (topHitCount > 0 && searchCommonHelper.isNeedPersonalSearch(paramMap)) {
  284 + topHitOrder = "_score:desc";
  285 + }
  286 +
  287 + // 4、构建searchParam
  288 + SearchParam searchParam = searchParamHelper.buildWithPersional(paramMap, topHitCount > 0 ? true : false);
  289 + IAggregation groupBrandAgg = aggregationFactoryService.getGroupBrandAggregation(topHitOrder, topHitCount);
  290 + searchParam.setAggregationBuilders(Arrays.asList(groupBrandAgg.getBuilder()));
  291 + searchParam.setSize(0);
  292 + searchParam.setOffset(topHitCount * 2);// justForCache
  293 +
  294 + // 5、从缓存中获取
  295 + final String productIndexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
  296 + JSONObject groupBrandResult = searchCacheService.getJSONObjectFromCache(this.searchCache, productIndexName, searchParam);
  297 + if (groupBrandResult != null) {
  298 + SearchCacheMatchLogger.doSearchCacheMatchLog("/productindex/groupBrands.json", paramMap);
  299 + return new SearchApiResult().setData(groupBrandResult);
  300 + }
  301 + // 6、从ES中获取
  302 + groupBrandResult = aggregationService.getAggNameAndResponseWithTotal(groupBrandAgg, searchParam);
  303 + if (groupBrandResult == null) {
  304 + return new SearchApiResult().setData(500).setMessage("exception");
  305 + }
  306 + // 7、生成结果并且加入缓存
  307 + JSONObject realResult = new JSONObject();
  308 + realResult.put("total", groupBrandResult.getOrDefault("total", 0));
  309 + realResult.put("brands", groupBrandResult.getOrDefault(groupBrandAgg.aggName(), new JSONObject()));
  310 + searchCacheService.addJSONObjectToCache(this.searchCache, productIndexName, searchParam, realResult);
  311 + return new SearchApiResult().setData(realResult).setMessage("groupBrands new List.");
  312 + } catch (Exception e) {
  313 + publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_GROUP_BRANDS.getEventName(), EventReportEnum.SEARCHCONTROLLER_GROUP_BRANDS.getFunctionName(),
  314 + EventReportEnum.SEARCHCONTROLLER_GROUP_BRANDS.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
  315 + return SearchApiResultUtils.errorSearchApiResult("groupBrands", paramMap, e);
  316 + }
  317 + }
  318 +
  319 +
  320 + @Override
  321 + public SearchApiResult aggProductsByBrandIdInParam(Map<String, String> paramMap) {
  322 + try {
  323 + logger.info("[func=aggProductsByBrandIdInParam][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
  324 +
  325 + // 1、参数校验
  326 + List<Integer> brandIds = ConvertUtils.stringToIntList(MapUtils.getString(paramMap, "brand", ""), ",");
  327 + if (brandIds == null || brandIds.isEmpty()) {
  328 + return new SearchApiResult().setCode(400).setMessage("没有 brand参数 ");
  329 + }
  330 +
  331 + // 2、处理排序方式
  332 + String sortField = searchSortHelper.getLegalOrder(paramMap);
  333 + if (StringUtils.isBlank(sortField)) {
  334 + sortField = "shelveTime:desc";
  335 + }
  336 + String[] sortParts = sortField.split(":");
  337 + String realSortField = sortParts[0];
  338 + String realSortType = sortParts[1];
  339 + SortOrder realSortOrder = SortOrder.ASC.toString().equalsIgnoreCase(realSortType) ? SortOrder.ASC : SortOrder.DESC;
  340 +
  341 + // 3、构造查询参数
  342 + SearchParam searchParam = searchParamHelper.buildDefault(paramMap);
  343 +
  344 + // 4、构造聚合参数
  345 + List<AbstractAggregationBuilder<?>> list = new ArrayList<AbstractAggregationBuilder<?>>();
  346 + // 获取取商品的数量
  347 + // 构造品牌聚合参数[最多取100个品牌的一个商品,取回来之后再做排序]
  348 + TermsAggregationBuilder brandAggregationBuilder = AggregationBuilders.terms("brandAgg").field(ProductIndexEsField.brandId).size(100);
  349 + // 再构造对应HIT到的商品的聚合参数
  350 + FieldSortBuilder productSortBuilder = SortBuilders.fieldSort(realSortField).order(realSortOrder);
  351 + TopHitsAggregationBuilder productTopHitsBuilder = AggregationBuilders.topHits("product").sort(productSortBuilder).size(1);
  352 + brandAggregationBuilder.subAggregation(productTopHitsBuilder);
  353 + list.add(brandAggregationBuilder);
  354 + searchParam.setAggregationBuilders(list);
  355 +
  356 + // 5、设置报文缓存参数
  357 + int limit = StringUtils.isBlank(paramMap.get("limit")) ? 1 : Integer.parseInt(paramMap.get("limit"));
  358 + searchParam.setOffset(limit);// 这个参数只是用来生成报文以做缓存,不要动
  359 + searchParam.setSize(0);
  360 +
  361 + // 6、构造返回结果
  362 + SearchApiResult searchApiResult = new SearchApiResult().setMessage("new product List.");
  363 +
  364 + // 7、先从缓存中获取,如果能取到,则直接返回
  365 + JSONArray jsonArray = searchCacheService.getJSONArrayFromCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
  366 + if (jsonArray != null) {
  367 + SearchCacheMatchLogger.doSearchCacheMatchLog("/new_product.json", paramMap);
  368 + return searchApiResult.setData(jsonArray);
  369 + }
  370 +
  371 + // 8、查询ES数据
  372 + final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
  373 + SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
  374 + if (searchResult == null || searchResult.getAggMaps() == null) {
  375 + return searchApiResult.setData("");
  376 + }
  377 + Map<String, Aggregation> aggMaps = searchResult.getAggMaps();
  378 + if (!aggMaps.containsKey("brandAgg")) {
  379 + return searchApiResult.setData("");
  380 + }
  381 +
  382 + // 9、构造返回数据并加入缓存
  383 + jsonArray = getNewBrandResponseMap(((MultiBucketsAggregation) aggMaps.get("brandAgg")), limit, brandIds, realSortField, realSortOrder);
  384 + searchCacheService.addJSONArrayToCache(this.searchCache, indexName, searchParam, jsonArray);
  385 + return searchApiResult.setData(jsonArray);
  386 + } catch (Exception e) {
  387 + publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_NEW_PRODUCT.getEventName(), EventReportEnum.SEARCHCONTROLLER_NEW_PRODUCT.getFunctionName(),
  388 + EventReportEnum.SEARCHCONTROLLER_NEW_PRODUCT.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
  389 + return SearchApiResultUtils.errorSearchApiResult("searchNewestProductWithDiffBrand", paramMap, e);
  390 + }
  391 + }
  392 +
  393 + private JSONArray getNewBrandResponseMap(MultiBucketsAggregation aggregation, int size, List<Integer> brandIds, final String realSortField, final SortOrder realSortOrder) {
  394 + // 1、首先获取全部品牌的商品列表
  395 + Iterator<? extends Bucket> itAgg = aggregation.getBuckets().iterator();
  396 + Map<String, Map<String, Object>> brandId2ProductMap = new HashMap<>();
  397 + while (itAgg.hasNext()) {
  398 + Bucket lt = itAgg.next();
  399 + if (lt.getAggregations().getAsMap().containsKey("product")) {
  400 + TopHits topHits = lt.getAggregations().get("product");
  401 + if (topHits != null) {
  402 + SearchHits hits = topHits.getHits();
  403 + for (SearchHit hit : hits.getHits()) {
  404 + brandId2ProductMap.put(lt.getKeyAsString(), hit.getSource());
  405 + }
  406 + }
  407 + }
  408 + }
  409 + if (brandId2ProductMap == null || brandId2ProductMap.isEmpty()) {
  410 + return new JSONArray();
  411 + }
  412 +
  413 + // 2、按品牌id获取商品列表
  414 + List<Map<String, Object>> productEsSourceList = new ArrayList<>();
  415 + for (Integer brandId : brandIds) {
  416 + if (brandId2ProductMap.containsKey(brandId.toString())) {
  417 + productEsSourceList.add(brandId2ProductMap.get(brandId.toString()));
  418 + }
  419 + if (productEsSourceList.size() >= size) {
  420 + break;
  421 + }
  422 + }
  423 +
  424 + // 3、对商品列表进行排序
  425 + Collections.sort(productEsSourceList, new Comparator<Map<String, Object>>() {
  426 + public int compare(Map<String, Object> o1, Map<String, Object> o2) {
  427 + Double map1value = MapUtils.getDoubleValue(o1, realSortField);
  428 + Double map2value = MapUtils.getDoubleValue(o2, realSortField);
  429 + if ("desc".equalsIgnoreCase(realSortOrder.name())) {
  430 + return map2value.compareTo(map1value);
  431 + } else {
  432 + return map1value.compareTo(map2value);
  433 + }
  434 + }
  435 + });
  436 +
  437 + //4、生成返回对象
  438 + List<Map<String, Object>> productReturnInfoList = productListHelper.buildReturnInfoByEsSourceList(productEsSourceList);
  439 + JSONArray jsonArray = new JSONArray();
  440 + jsonArray.addAll(productReturnInfoList);
  441 + return jsonArray;
  442 + }
461 } 443 }