Authored by hugufei

BrandWithShopsService接口优化

@@ -3,7 +3,6 @@ package com.yoho.search.service.scene.shopbrand; @@ -3,7 +3,6 @@ package com.yoho.search.service.scene.shopbrand;
3 import com.alibaba.fastjson.JSONArray; 3 import com.alibaba.fastjson.JSONArray;
4 import com.alibaba.fastjson.JSONObject; 4 import com.alibaba.fastjson.JSONObject;
5 import com.yoho.error.event.SearchEvent; 5 import com.yoho.error.event.SearchEvent;
6 -import com.yoho.search.aop.cache.SearchCacheAble;  
7 import com.yoho.search.base.utils.EventReportEnum; 6 import com.yoho.search.base.utils.EventReportEnum;
8 import com.yoho.search.base.utils.ISearchConstants; 7 import com.yoho.search.base.utils.ISearchConstants;
9 import com.yoho.search.base.utils.ProductIndexEsField; 8 import com.yoho.search.base.utils.ProductIndexEsField;
@@ -24,7 +23,6 @@ import org.elasticsearch.search.aggregations.Aggregation; @@ -24,7 +23,6 @@ import org.elasticsearch.search.aggregations.Aggregation;
24 import org.elasticsearch.search.aggregations.AggregationBuilders; 23 import org.elasticsearch.search.aggregations.AggregationBuilders;
25 import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation; 24 import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation;
26 import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation.Bucket; 25 import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation.Bucket;
27 -import org.elasticsearch.search.aggregations.bucket.terms.Terms;  
28 import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder; 26 import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
29 import org.slf4j.Logger; 27 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory; 28 import org.slf4j.LoggerFactory;
@@ -56,23 +54,21 @@ public class BrandWithShopsService implements ApplicationEventPublisherAware { @@ -56,23 +54,21 @@ public class BrandWithShopsService implements ApplicationEventPublisherAware {
56 this.publisher = applicationEventPublisher; 54 this.publisher = applicationEventPublisher;
57 } 55 }
58 56
59 - @SearchCacheAble(cacheInMinute = 15, cacheName = "BRANDS_WITH_SHOPS", excludeParams = {"viewNum", "uid", "udid"}) 57 + //@SearchCacheAble(cacheInMinute = 15, cacheName = "BRANDS_WITH_SHOPS", excludeParams = {"viewNum", "uid", "udid"})
60 public SearchApiResult brandsWithShops(Map<String, String> paramMap) { 58 public SearchApiResult brandsWithShops(Map<String, String> paramMap) {
61 try { 59 try {
62 logger.info("[func=brandsWithShops][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis()); 60 logger.info("[func=brandsWithShops][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
63 // 1、构造查询参数 61 // 1、构造查询参数
64 SearchParam searchParam = searchParamHelper.buildDefault(paramMap); 62 SearchParam searchParam = searchParamHelper.buildDefault(paramMap);
65 // 2、构造聚合参数 63 // 2、构造聚合参数
66 - List<AbstractAggregationBuilder<?>> list = new ArrayList<AbstractAggregationBuilder<?>>();  
67 - // 2.1)父聚合:brandAlif  
68 - TermsAggregationBuilder brandAlifAgg = AggregationBuilders.terms("brandAlifAgg").field(ProductIndexEsField.brandAlif).size(200).order(Terms.Order.term(true));  
69 - // 2.2)子聚合:brandId  
70 - TermsAggregationBuilder brandIdAgg = AggregationBuilders.terms("brandIdAgg").field(ProductIndexEsField.brandId).size(1000);  
71 - // 2.3)孙聚合:shop 64 + List<AbstractAggregationBuilder<?>> list = new ArrayList<>();
  65 + // 2.1)父聚合:brandId
  66 + TermsAggregationBuilder brandIdAgg = AggregationBuilders.terms("brandIdAgg").field(ProductIndexEsField.brandId).size(3000);
  67 + // 2.2)子聚合:shopId
72 TermsAggregationBuilder shopAgg = AggregationBuilders.terms("shopIdAgg").field(ProductIndexEsField.shopId).size(30); 68 TermsAggregationBuilder shopAgg = AggregationBuilders.terms("shopIdAgg").field(ProductIndexEsField.shopId).size(30);
73 - // 2.4)曾孙聚合:是否全球购 69 + // 2.3)孙聚合:是否全球购
74 TermsAggregationBuilder globalAgg = AggregationBuilders.terms("isGlobalAgg").field(ProductIndexEsField.isGlobal).size(5); 70 TermsAggregationBuilder globalAgg = AggregationBuilders.terms("isGlobalAgg").field(ProductIndexEsField.isGlobal).size(5);
75 - list.add(brandAlifAgg.subAggregation(brandIdAgg.subAggregation(shopAgg.subAggregation(globalAgg)))); 71 + list.add(brandIdAgg.subAggregation(shopAgg.subAggregation(globalAgg)));
76 searchParam.setAggregationBuilders(list); 72 searchParam.setAggregationBuilders(list);
77 73
78 // 3、查询ES 74 // 3、查询ES
@@ -82,12 +78,14 @@ public class BrandWithShopsService implements ApplicationEventPublisherAware { @@ -82,12 +78,14 @@ public class BrandWithShopsService implements ApplicationEventPublisherAware {
82 return searchApiResult.setCode(500); 78 return searchApiResult.setCode(500);
83 } 79 }
84 Map<String, Aggregation> aggregationResult = searchResult.getAggMaps(); 80 Map<String, Aggregation> aggregationResult = searchResult.getAggMaps();
85 - if (!aggregationResult.containsKey("brandAlifAgg")) { 81 + if (!aggregationResult.containsKey("brandIdAgg")) {
86 return searchApiResult; 82 return searchApiResult;
87 } 83 }
88 - // 4、构造返回结果并加入缓存 84 + Map<String, List<BrandShopInfo>> brandId2ShopInfoList = this.buildBrandId2ShopInfoList(aggregationResult);
  85 +
  86 + // 4、构造返回结果
89 JSONObject result = new JSONObject(); 87 JSONObject result = new JSONObject();
90 - result.put("brands", makeBrandResponse(((MultiBucketsAggregation) aggregationResult.get("brandAlifAgg")))); 88 + result.put("brands", buildRealResults(brandId2ShopInfoList));
91 return searchApiResult.setData(result); 89 return searchApiResult.setData(result);
92 } catch (Exception e) { 90 } catch (Exception e) {
93 publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_BRANDS.getEventName(), EventReportEnum.SEARCHCONTROLLER_BRANDS.getFunctionName(), 91 publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_BRANDS.getEventName(), EventReportEnum.SEARCHCONTROLLER_BRANDS.getFunctionName(),
@@ -96,101 +94,120 @@ public class BrandWithShopsService implements ApplicationEventPublisherAware { @@ -96,101 +94,120 @@ public class BrandWithShopsService implements ApplicationEventPublisherAware {
96 } 94 }
97 } 95 }
98 96
99 - private MultiBucketsAggregation getMultiBucketsAggregation(Bucket bucket, String aggName) {  
100 - return (MultiBucketsAggregation) bucket.getAggregations().asMap().get(aggName);  
101 - }  
102 -  
103 - /**  
104 - * 制作品牌报文  
105 - */  
106 - private Map<String, JSONArray> makeBrandResponse(MultiBucketsAggregation aggregation) {  
107 - // 1)获取每个brandAlif-->brandId->List<BrandShopInfo>  
108 - Map<String, Map<String, List<BrandShopInfo>>> brandAlif2BrandShopInfos = new LinkedHashMap<String, Map<String, List<BrandShopInfo>>>();  
109 - for (Bucket brandAlifBucket : aggregation.getBuckets()) {  
110 - String brandAlif = brandAlifBucket.getKeyAsString();  
111 - Map<String, List<BrandShopInfo>> brandWithShopsListMap = new LinkedHashMap<String, List<BrandShopInfo>>();  
112 - MultiBucketsAggregation brandIdAgg = this.getMultiBucketsAggregation(brandAlifBucket, "brandIdAgg");  
113 - for (Bucket brandIdBucket : brandIdAgg.getBuckets()) {  
114 - String brandId = brandIdBucket.getKeyAsString();  
115 - List<BrandShopInfo> brandShopInfoList = new ArrayList<BrandShopInfo>();  
116 - MultiBucketsAggregation shopIdAggs = this.getMultiBucketsAggregation(brandIdBucket, "shopIdAgg");  
117 - for (Bucket shopIdBucket : shopIdAggs.getBuckets()) {  
118 - String shopId = shopIdBucket.getKeyAsString();  
119 - MultiBucketsAggregation isGlobalAgg = this.getMultiBucketsAggregation(shopIdBucket, "isGlobalAgg");  
120 - for (Bucket isGlobalBucket : isGlobalAgg.getBuckets()) {  
121 - String isGlobal = isGlobalBucket.getKeyAsString();  
122 - BrandShopInfo brandShopInfo = new BrandShopInfo(shopId, isGlobal);  
123 - if (this.isBrandShopInfoLegal(brandShopInfo)) {  
124 - brandShopInfoList.add(brandShopInfo);  
125 - } 97 + // 构造每个brandId对应的List<BrandShopInfo>
  98 + private Map<String, List<BrandShopInfo>> buildBrandId2ShopInfoList(Map<String, Aggregation> aggregationResult) {
  99 + Map<String, List<BrandShopInfo>> results = new LinkedHashMap<>();
  100 + if (!aggregationResult.containsKey("brandIdAgg")) {
  101 + return results;
  102 + }
  103 + MultiBucketsAggregation brandIdAgg = ((MultiBucketsAggregation) aggregationResult.get("brandIdAgg"));
  104 + for (Bucket brandIdBucket : brandIdAgg.getBuckets()) {
  105 + String brandId = brandIdBucket.getKeyAsString();
  106 + List<BrandShopInfo> brandShopInfoList = new ArrayList<>();
  107 + MultiBucketsAggregation shopIdAggs = (MultiBucketsAggregation) brandIdBucket.getAggregations().asMap().get("shopIdAgg");
  108 + for (Bucket shopIdBucket : shopIdAggs.getBuckets()) {
  109 + String shopId = shopIdBucket.getKeyAsString();
  110 + MultiBucketsAggregation isGlobalAgg = (MultiBucketsAggregation) shopIdBucket.getAggregations().asMap().get("isGlobalAgg");
  111 + for (Bucket isGlobalBucket : isGlobalAgg.getBuckets()) {
  112 + String isGlobal = isGlobalBucket.getKeyAsString();
  113 + BrandShopInfo brandShopInfo = new BrandShopInfo(shopId, isGlobal);
  114 + if (this.isBrandShopInfoLegal(brandShopInfo)) {
  115 + brandShopInfoList.add(brandShopInfo);
126 } 116 }
127 } 117 }
128 - brandWithShopsListMap.put(brandId, brandShopInfoList);  
129 } 118 }
130 - brandAlif2BrandShopInfos.put(brandAlif, brandWithShopsListMap); 119 + results.put(brandId, brandShopInfoList);
131 } 120 }
132 - // 2)获取所有的品牌id和有货单品点的店铺id  
133 - List<String> brandIds = new ArrayList<String>();  
134 - List<String> shopIds = new ArrayList<String>();  
135 - List<String> globalBrandIds = new ArrayList<String>(); 121 + return results;
  122 + }
136 123
137 - for (Map.Entry<String, Map<String, List<BrandShopInfo>>> entry : brandAlif2BrandShopInfos.entrySet()) {  
138 - Map<String, List<BrandShopInfo>> brandShopInfoMap = entry.getValue();  
139 - for (Map.Entry<String, List<BrandShopInfo>> brandShopInfoMapEntry : brandShopInfoMap.entrySet()) {  
140 - brandIds.add(brandShopInfoMapEntry.getKey());  
141 - List<BrandShopInfo> brandShopInfoList = brandShopInfoMapEntry.getValue();  
142 - for (BrandShopInfo brandShopInfo : brandShopInfoList) {  
143 - shopIds.add(brandShopInfo.getShopId());  
144 - if ("Y".equals(brandShopInfo.getIsGlobal())) {  
145 - globalBrandIds.add(brandShopInfoMapEntry.getKey());  
146 - } 124 + private Map<String, JSONArray> buildRealResults(Map<String, List<BrandShopInfo>> brandId2ShopInfoList) {
  125 + // 1)获取所有的品牌id和有货单品店的店铺id
  126 + List<String> brandIds = new ArrayList<>();
  127 + List<String> shopIds = new ArrayList<>();
  128 + List<String> globalBrandIds = new ArrayList<>();
  129 + for (Map.Entry<String, List<BrandShopInfo>> brandShopInfoMapEntry : brandId2ShopInfoList.entrySet()) {
  130 + brandIds.add(brandShopInfoMapEntry.getKey());
  131 + List<BrandShopInfo> brandShopInfoList = brandShopInfoMapEntry.getValue();
  132 + for (BrandShopInfo brandShopInfo : brandShopInfoList) {
  133 + shopIds.add(brandShopInfo.getShopId());
  134 + if ("Y".equals(brandShopInfo.getIsGlobal())) {
  135 + globalBrandIds.add(brandShopInfoMapEntry.getKey());
147 } 136 }
148 } 137 }
149 } 138 }
150 - // 3)获取所有的品牌数据  
151 - Map<String, Map<String, Object>> brandInfoMap = brandIndexBaseService.getBrandMapByIds(brandIds,true);  
152 - // 4)获取所有的全球购品牌数据 139 +
  140 + // 2)获取所有的品牌数据
  141 + Map<String, Map<String, Object>> brandInfoMap = brandIndexBaseService.getBrandMapByIds(brandIds, true);
  142 + // 3)获取所有的全球购品牌数据
153 Map<String, Map<String, Object>> globalBrandInfoMap = brandIndexBaseService.getGlobalBrandMapByIds(globalBrandIds, 1); 143 Map<String, Map<String, Object>> globalBrandInfoMap = brandIndexBaseService.getGlobalBrandMapByIds(globalBrandIds, 1);
154 - // 5)获取所有的有货店铺数据 144 + // 4)获取所有的有货店铺数据
155 Map<String, Map<String, Object>> shopInfoMap = shopsIndexBaseService.getShopsMapByIds(shopIds); 145 Map<String, Map<String, Object>> shopInfoMap = shopsIndexBaseService.getShopsMapByIds(shopIds);
156 146
157 - // 6)构造真正的数据  
158 - Map<String, JSONArray> result = new LinkedHashMap<String, JSONArray>();  
159 - for (Map.Entry<String, Map<String, List<BrandShopInfo>>> aliafEntry : brandAlif2BrandShopInfos.entrySet()) {  
160 - String brandAlif = aliafEntry.getKey();  
161 - List<JSONObject> brandWithShopsInfo = new ArrayList<JSONObject>();  
162 - for (Map.Entry<String, List<BrandShopInfo>> entry : aliafEntry.getValue().entrySet()) {  
163 - String brandId = entry.getKey();  
164 - Map<String, Object> brandInfo = brandInfoMap.get(brandId);  
165 - if (brandInfo == null || MapUtils.getIntValue(brandInfo, "status", 0) != 1) {  
166 - continue;  
167 - }  
168 - JSONObject shop_info = new JSONObject();  
169 - List<BrandShopInfo> brandShopInfoList = entry.getValue();  
170 - JSONArray shop_yoho_list = this.getYohoShopInfo(brandShopInfoList, shopInfoMap);  
171 - shop_info.put("yoho_shop_list", shop_yoho_list);  
172 - shop_info.put("yoho_shop_count", shop_yoho_list.size());  
173 - JSONArray global_brand_List = this.getGlobalBrandList(brandShopInfoList, brandId, globalBrandInfoMap);  
174 - shop_info.put("global_brand_List", global_brand_List);  
175 - shop_info.put("global_brand_count", global_brand_List.size());  
176 - brandInfo.put("shop_info", shop_info);  
177 - brandWithShopsInfo.add(new JSONObject(brandInfo)); 147 + // 5)构建brandWithShopsInfoList
  148 + List<JSONObject> brandWithShopsInfoList = new ArrayList<>();
  149 + for (Map.Entry<String, List<BrandShopInfo>> entry : brandId2ShopInfoList.entrySet()) {
  150 + String brandId = entry.getKey();
  151 + Map<String, Object> brandInfo = brandInfoMap.get(brandId);
  152 + if (brandInfo == null || MapUtils.getIntValue(brandInfo, "status", 0) != 1) {
  153 + continue;
178 } 154 }
179 - if (brandWithShopsInfo.isEmpty()) { 155 + JSONObject shop_info = new JSONObject();
  156 + List<BrandShopInfo> brandShopInfoList = entry.getValue();
  157 + JSONArray shop_yoho_list = this.getYohoShopInfo(brandShopInfoList, shopInfoMap);
  158 + shop_info.put("yoho_shop_list", shop_yoho_list);
  159 + shop_info.put("yoho_shop_count", shop_yoho_list.size());
  160 + JSONArray global_brand_List = this.getGlobalBrandList(brandShopInfoList, brandId, globalBrandInfoMap);
  161 + shop_info.put("global_brand_List", global_brand_List);
  162 + shop_info.put("global_brand_count", global_brand_List.size());
  163 + brandInfo.put("shop_info", shop_info);
  164 + brandWithShopsInfoList.add(new JSONObject(brandInfo));
  165 + }
  166 +
  167 + // 6) 出现STORE by NIGO®时添加HUMAN_MADE的壳子【439->2512】
  168 + this.addHUMAN_MADE(brandWithShopsInfoList);
  169 +
  170 + // 7) 按brand_name_for_sort整体排序
  171 + Collections.sort(brandWithShopsInfoList, (o1, o2) -> MapUtils.getString(o1, "brand_name_for_sort", "#").compareToIgnoreCase(MapUtils.getString(o2, "brand_name_for_sort", "#")));
  172 +
  173 + //8) 除brand_name_for_sort, 并按brand_alif分组并移
  174 + Map<String, JSONArray> realResults = new TreeMap<>();
  175 + for (JSONObject brandWithShopsInfo : brandWithShopsInfoList) {
  176 + brandWithShopsInfo.remove("brand_name_for_sort");
  177 + String brand_alif = MapUtils.getString(brandWithShopsInfo, "brand_alif", "");
  178 + if (StringUtils.isBlank(brand_alif)) {
180 continue; 179 continue;
181 } 180 }
182 - //按brand_name_for_sort排序  
183 - Collections.sort(brandWithShopsInfo, (o1, o2) ->  
184 - MapUtils.getString(o1, "brand_name_for_sort", "#").compareToIgnoreCase(MapUtils.getString(o2, "brand_name_for_sort", "#"))  
185 - );  
186 - JSONArray brandWithShopsInfoJsonArray = new JSONArray();  
187 - for (JSONObject brandInfo : brandWithShopsInfo) {  
188 - brandInfo.remove("brand_name_for_sort");  
189 - brandWithShopsInfoJsonArray.add(brandInfo); 181 + JSONArray jsonArray = realResults.computeIfAbsent(brand_alif, k -> new JSONArray());
  182 + jsonArray.add(brandWithShopsInfo);
  183 + }
  184 + return realResults;
  185 + }
  186 +
  187 + // 出现STORE by NIGO®时添加HUMAN_MADE的壳子【439->2512】
  188 + private void addHUMAN_MADE(List<JSONObject> brandWithShopsInfoList) {
  189 + JSONObject HUMAN_MADE = null;
  190 + for (JSONObject brandWithShopsInfo : brandWithShopsInfoList) {
  191 + int brandId = MapUtils.getIntValue(brandWithShopsInfo, "id", 0);
  192 + //如果有HUMAN_MADE[2512],直接返回不添加
  193 + if (brandId == 2512) {
  194 + return;
  195 + }
  196 + //如果有STORE by NIGO®[439],则生成HUMAN_MADE的壳子
  197 + if (brandId == 1036) {
  198 + HUMAN_MADE = new JSONObject();
  199 + HUMAN_MADE.putAll(brandWithShopsInfo);
  200 + HUMAN_MADE.put("brand_alif", "H");//分组
  201 + HUMAN_MADE.put("brand_name", "HUMAN MADE");//显示
  202 + HUMAN_MADE.put("brand_name_en", "HUMAN MADE");
  203 + HUMAN_MADE.put("brand_name_cn", "HUMAN MADE");
  204 + HUMAN_MADE.put("brand_name_for_sort", "humanmade");//排序
  205 + continue;
190 } 206 }
191 - result.put(brandAlif, brandWithShopsInfoJsonArray);  
192 } 207 }
193 - return result; 208 + if (HUMAN_MADE != null) {
  209 + brandWithShopsInfoList.add(HUMAN_MADE);
  210 + }
194 } 211 }
195 212
196 /** 213 /**