Authored by hugufei

Merge branch 'master' into wn_promotion

Conflicts:
	service/src/main/java/com/yoho/search/recall/scene/beans/cache/UserRecallCacheBean.java
	service/src/main/java/com/yoho/search/recall/scene/beans/persional/AbstractPageComponent.java
	service/src/main/java/com/yoho/search/recall/scene/beans/persional/PageProductIdBitSetComponent.java
	service/src/main/java/com/yoho/search/recall/scene/beans/strategy/impls/RecommendSknStrategy.java
	service/src/main/java/com/yoho/search/recall/scene/models/personal/PageProductIdBitSet.java
1 package com.yoho.search.recall.scene.beans.builder; 1 package com.yoho.search.recall.scene.beans.builder;
2 2
3 import com.yoho.search.recall.scene.beans.cache.SknBaseInfoCacheBean; 3 import com.yoho.search.recall.scene.beans.cache.SknBaseInfoCacheBean;
4 -import com.yoho.search.recall.scene.models.req.RecallRequestResponse; 4 +import com.yoho.search.recall.scene.beans.strategy.StrategyEnum;
  5 +import com.yoho.search.recall.scene.models.common.RecallMergerResult;
5 import com.yoho.search.recall.scene.models.req.RecallRequest; 6 import com.yoho.search.recall.scene.models.req.RecallRequest;
  7 +import com.yoho.search.recall.scene.models.req.RecallRequestResponse;
6 import com.yoho.search.recall.scene.models.req.RecallResponse; 8 import com.yoho.search.recall.scene.models.req.RecallResponse;
7 -import com.yoho.search.recall.scene.models.common.RecallMergerResult;  
8 -import com.yoho.search.recall.scene.beans.strategy.StrategyEnum;  
9 -import com.yoho.search.recall.scene.models.req.SknBaseInfoResponse;  
10 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.beans.factory.annotation.Autowired;
11 import org.springframework.stereotype.Component; 10 import org.springframework.stereotype.Component;
12 11
13 -import java.util.ArrayList;  
14 -import java.util.HashMap;  
15 -import java.util.List;  
16 -import java.util.Map; 12 +import java.util.*;
17 13
18 @Component 14 @Component
19 public class RecallMergerResultBuilder { 15 public class RecallMergerResultBuilder {
@@ -85,10 +81,11 @@ public class RecallMergerResultBuilder { @@ -85,10 +81,11 @@ public class RecallMergerResultBuilder {
85 strategyList.add(request.requestStrategy()); 81 strategyList.add(request.requestStrategy());
86 } 82 }
87 } 83 }
88 - //2、填充Strategys 84 + //2、填充Strategy,按优先级排序
89 for (RecallMergerResult.SknResult sknResult : sknResults) { 85 for (RecallMergerResult.SknResult sknResult : sknResults) {
90 List<StrategyEnum> strategyEnumList = skn2StrategyListMap.getOrDefault(sknResult.getProductSkn(), new ArrayList<>()); 86 List<StrategyEnum> strategyEnumList = skn2StrategyListMap.getOrDefault(sknResult.getProductSkn(), new ArrayList<>());
91 - sknResult.setStrategys(strategyEnumList); 87 + Collections.sort(strategyEnumList, (o1, o2) -> o2.getPriority().compareTo(o1.getPriority()));
  88 + sknResult.setStrategy(strategyEnumList.get(0));//取优先级最高的召回策略
92 } 89 }
93 return sknResults; 90 return sknResults;
94 } 91 }
1 package com.yoho.search.recall.scene.beans.builder; 1 package com.yoho.search.recall.scene.beans.builder;
2 2
3 import com.yoho.search.base.utils.CollectionUtils; 3 import com.yoho.search.base.utils.CollectionUtils;
  4 +import com.yoho.search.base.utils.Transfer;
4 import com.yoho.search.core.personalized.PersonalizedSearch; 5 import com.yoho.search.core.personalized.PersonalizedSearch;
5 import com.yoho.search.core.personalized.models.SortPriceAreas; 6 import com.yoho.search.core.personalized.models.SortPriceAreas;
6 import com.yoho.search.recall.performance.beans.ProductFeatureFactorHepler; 7 import com.yoho.search.recall.performance.beans.ProductFeatureFactorHepler;
@@ -23,6 +24,7 @@ import org.slf4j.Logger; @@ -23,6 +24,7 @@ import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory; 24 import org.slf4j.LoggerFactory;
24 import org.springframework.beans.factory.annotation.Autowired; 25 import org.springframework.beans.factory.annotation.Autowired;
25 import org.springframework.stereotype.Component; 26 import org.springframework.stereotype.Component;
  27 +import sun.applet.Main;
26 28
27 import java.util.*; 29 import java.util.*;
28 30
@@ -67,9 +69,8 @@ public class UserRecallResponseBuilder { @@ -67,9 +69,8 @@ public class UserRecallResponseBuilder {
67 //7、处理firstSkn-直通车等信息 69 //7、处理firstSkn-直通车等信息
68 sknResultList = this.doReRank(sknResultList); 70 sknResultList = this.doReRank(sknResultList);
69 71
70 - //8、策略优先级排序并添加日志 72 + //8、添加日志
71 for (RecallMergerResult.SknResult sknResult : sknResultList) { 73 for (RecallMergerResult.SknResult sknResult : sknResultList) {
72 - Collections.sort(sknResult.getStrategys(), (o1, o2) -> o2.getPriority().compareTo(o1.getPriority()));  
73 this.logSknStrategyAndScore(userRecallRequest, sknResult); 74 this.logSknStrategyAndScore(userRecallRequest, sknResult);
74 } 75 }
75 76
@@ -85,8 +86,7 @@ public class UserRecallResponseBuilder { @@ -85,8 +86,7 @@ public class UserRecallResponseBuilder {
85 //10、构造返回结果 86 //10、构造返回结果
86 List<RecallSknInfo> sknList = new ArrayList<>(); 87 List<RecallSknInfo> sknList = new ArrayList<>();
87 for (RecallMergerResult.SknResult sknResult : sknResultList) { 88 for (RecallMergerResult.SknResult sknResult : sknResultList) {
88 - String requestType = sknResult.getStrategys().get(0).name();//策略已经排过序了,取第一个就好  
89 - sknList.add(new RecallSknInfo(sknResult.getProductSkn(), requestType)); 89 + sknList.add(new RecallSknInfo(sknResult.getProductSkn(), sknResult.getStrategy().name()));
90 } 90 }
91 int recallTotal = sknResultList.size(); 91 int recallTotal = sknResultList.size();
92 return new UserRecallResponse(total, recallTotal, recallTotalPage, sknList); 92 return new UserRecallResponse(total, recallTotal, recallTotalPage, sknList);
@@ -119,7 +119,7 @@ public class UserRecallResponseBuilder { @@ -119,7 +119,7 @@ public class UserRecallResponseBuilder {
119 return; 119 return;
120 } 120 }
121 try { 121 try {
122 - RECALL_NEW_LOGGER.info("skn is[{}], strategy is [{}],score is[{}] ", sknResult.getProductSkn(), sknResult.getStrategys().get(0).name(), sknResult.getScore()); 122 + RECALL_NEW_LOGGER.info("skn is[{}], strategy is [{}],score is[{}] ", sknResult.getProductSkn(), sknResult.getStrategy().name(), sknResult.getScore());
123 } catch (Exception e) { 123 } catch (Exception e) {
124 RECALL_NEW_LOGGER.error(e.getMessage(), e); 124 RECALL_NEW_LOGGER.error(e.getMessage(), e);
125 } 125 }
@@ -134,7 +134,7 @@ public class UserRecallResponseBuilder { @@ -134,7 +134,7 @@ public class UserRecallResponseBuilder {
134 private List<RecallMergerResult.SknResult> fillIsLikePriceArea(List<RecallMergerResult.SknResult> sknResults, UserPersonalFactor userPersonalFactor) { 134 private List<RecallMergerResult.SknResult> fillIsLikePriceArea(List<RecallMergerResult.SknResult> sknResults, UserPersonalFactor userPersonalFactor) {
135 //1、获取用户价格带偏好 135 //1、获取用户价格带偏好
136 List<SortPriceAreas> userSortPriceAreasList = userPersonalFactor.getSortPriceAreasList(); 136 List<SortPriceAreas> userSortPriceAreasList = userPersonalFactor.getSortPriceAreasList();
137 - if(userSortPriceAreasList==null || userSortPriceAreasList.isEmpty()){ 137 + if (userSortPriceAreasList == null || userSortPriceAreasList.isEmpty()) {
138 return sknResults; 138 return sknResults;
139 } 139 }
140 //2、生成品类价格带偏好的Map 140 //2、生成品类价格带偏好的Map
@@ -169,20 +169,30 @@ public class UserRecallResponseBuilder { @@ -169,20 +169,30 @@ public class UserRecallResponseBuilder {
169 PersonalizedSearch personalizedSearch = personalVectorFeatureSearch.getPersonalizedSearch(paramMap); 169 PersonalizedSearch personalizedSearch = personalVectorFeatureSearch.getPersonalizedSearch(paramMap);
170 UserFeatureFactor userFeatureFactor = new UserFeatureFactor(personalizedSearch); 170 UserFeatureFactor userFeatureFactor = new UserFeatureFactor(personalizedSearch);
171 //2、计算相关性 171 //2、计算相关性
  172 + int recommendSknIndex = 1000;
172 for (RecallMergerResult.SknResult sknResult : sknResultList) { 173 for (RecallMergerResult.SknResult sknResult : sknResultList) {
173 - double score = productFeatureFactorHepler.calProductFeatureFactor(userFeatureFactor, sknResult.getFactor());  
174 - //1)如果满足品类价格带偏好,则加分 174 + double score = 0d;
  175 + //1)策略判断
  176 + StrategyEnum strategy = sknResult.getStrategy();
  177 + if (strategy == null) {
  178 + sknResult.setScore(score);
  179 + continue;
  180 + }
  181 + //2)如果是推荐出来的,则单独加分[以减分的方式依次保证顺序]
  182 + if (strategy.equals(StrategyEnum.RECOMMEND_SKN)) {
  183 + sknResult.setScore((double) recommendSknIndex--);
  184 + continue;
  185 + }
  186 + //3)向量计算
  187 + score = productFeatureFactorHepler.calProductFeatureFactor(userFeatureFactor, sknResult.getFactor());
  188 + //4)如果满足品类价格带偏好,则加分
175 if (sknResult.isLikePriceArea()) { 189 if (sknResult.isLikePriceArea()) {
176 score = score + 100; 190 score = score + 100;
177 } 191 }
178 - //2)如果兜底策略不参与评分,并且当前skn有其他的召回策略,则加分【将兜底和非兜底的拆分】  
179 - if (!searchDynamicConfigService.searchPersionalNewStrategyCommonJoinScoreOpen() && !this.isCommonRecallOnly(sknResult)) { 192 + //5)如果兜底策略不参与评分,并且当前skn不是兜底召回的,则加分【将兜底和非兜底的拆分】
  193 + if (!searchDynamicConfigService.searchPersionalNewStrategyCommonJoinScoreOpen() && !strategy.equals(StrategyEnum.COMMON)) {
180 score = score + 50; 194 score = score + 50;
181 } 195 }
182 - //3)如果是推荐出来的,则单独加分  
183 - if (sknResult.getStrategys().contains(StrategyEnum.RECOMMEND_SKN)){  
184 - score = score + 200;  
185 - }  
186 sknResult.setScore(score); 196 sknResult.setScore(score);
187 } 197 }
188 //3、按得分排序-得分高的在前面 198 //3、按得分排序-得分高的在前面
@@ -191,25 +201,6 @@ public class UserRecallResponseBuilder { @@ -191,25 +201,6 @@ public class UserRecallResponseBuilder {
191 } 201 }
192 202
193 /** 203 /**
194 - * 当前商品是否只是兜底策略找回来的  
195 - *  
196 - * @param sknResult  
197 - * @return  
198 - */  
199 - private boolean isCommonRecallOnly(RecallMergerResult.SknResult sknResult) {  
200 - List<StrategyEnum> strategys = sknResult.getStrategys();  
201 - //1、非空判断  
202 - if (strategys == null || strategys.isEmpty()) {  
203 - return true;  
204 - }  
205 - //2、只是兜底策略  
206 - if (strategys.size() == 1 && strategys.get(0).equals(StrategyEnum.COMMON)) {  
207 - return true;  
208 - }  
209 - return false;  
210 - }  
211 -  
212 - /**  
213 * 精排-品类品牌平衡 204 * 精排-品类品牌平衡
214 * 205 *
215 * @param sknResultList 206 * @param sknResultList
@@ -237,43 +228,84 @@ public class UserRecallResponseBuilder { @@ -237,43 +228,84 @@ public class UserRecallResponseBuilder {
237 */ 228 */
238 private List<RecallMergerResult.SknResult> doReRank(List<RecallMergerResult.SknResult> sknResultList) { 229 private List<RecallMergerResult.SknResult> doReRank(List<RecallMergerResult.SknResult> sknResultList) {
239 List<RecallMergerResult.SknResult> results = new ArrayList<>(); 230 List<RecallMergerResult.SknResult> results = new ArrayList<>();
240 - // 1、firstSkn排第一个 231 +
  232 + //1、插入first_skn
241 Iterator<RecallMergerResult.SknResult> iterator = sknResultList.iterator(); 233 Iterator<RecallMergerResult.SknResult> iterator = sknResultList.iterator();
242 while (iterator.hasNext()) { 234 while (iterator.hasNext()) {
243 RecallMergerResult.SknResult sknResult = iterator.next(); 235 RecallMergerResult.SknResult sknResult = iterator.next();
244 - if (sknResult.getStrategys().contains(StrategyEnum.FIRST_SKN)) { 236 + if (sknResult.getStrategy().equals(StrategyEnum.FIRST_SKN)) {
245 results.add(sknResult); 237 results.add(sknResult);
246 iterator.remove(); 238 iterator.remove();
247 break; 239 break;
248 } 240 }
249 } 241 }
250 - // 2、加入全部【除直通车】外的商品 242 +
  243 + // 2、加入全部【除直通车和直接推荐】外的商品
251 iterator = sknResultList.iterator(); 244 iterator = sknResultList.iterator();
252 while (iterator.hasNext()) { 245 while (iterator.hasNext()) {
253 RecallMergerResult.SknResult sknResult = iterator.next(); 246 RecallMergerResult.SknResult sknResult = iterator.next();
254 - if (!sknResult.getStrategys().contains(StrategyEnum.DIRECT_TRAIN)) { 247 + if (!Arrays.asList(StrategyEnum.DIRECT_TRAIN,StrategyEnum.RECOMMEND_SKN).contains(sknResult.getStrategy())){
255 results.add(sknResult); 248 results.add(sknResult);
256 iterator.remove(); 249 iterator.remove();
257 } 250 }
258 } 251 }
259 - // 3、插入【直通车】商品  
260 - iterator = sknResultList.iterator();  
261 - int index = 1; 252 +
  253 + // 3、插入【直接推荐】的商品-随机插入
  254 + this.addByIndexIndex(sknResultList, results, 1, 2, (sknResult -> StrategyEnum.RECOMMEND_SKN.equals(sknResult.getStrategy())));
  255 +
  256 + // 4、插入【直通车】商品
262 int directTrainIndexInterval = searchDynamicConfigService.directTrainIndexInterval(); 257 int directTrainIndexInterval = searchDynamicConfigService.directTrainIndexInterval();
  258 + this.addByIndexIndex(sknResultList, results, 4, directTrainIndexInterval, (sknResult -> StrategyEnum.DIRECT_TRAIN.equals(sknResult.getStrategy())));
  259 +
  260 + return results;
  261 + }
  262 +
  263 + private static <T> void addByIndexIndex(List<T> fromList, List<T> toList,int fromIndex, int indexInterval,Transfer<T, Boolean> match) {
  264 + Iterator<T> iterator = fromList.iterator();
263 while (iterator.hasNext()) { 265 while (iterator.hasNext()) {
264 - RecallMergerResult.SknResult sknResult = iterator.next();  
265 - // 生成插入位置-超出新列表的长度,则直接丢弃  
266 - int totalNewProductListSize = results.size();  
267 - int randomIndex = (int) (directTrainIndexInterval * (index++ + Math.random()));  
268 - if (randomIndex == 0 && !results.isEmpty()) {  
269 - randomIndex = 1;//不影响firstSkn 266 + T object = iterator.next();
  267 + if (!match.transfer(object)) {
  268 + continue;
270 } 269 }
271 - if (randomIndex <= totalNewProductListSize) {  
272 - results.add(randomIndex, sknResult); 270 + // 生成插入位置
  271 + int toListNewSize = toList.size();
  272 + System.out.println(fromIndex);
  273 + // 尽量不影响第1个
  274 + if (fromIndex == 0 && !toList.isEmpty()) {
  275 + fromIndex = 1;
  276 + }
  277 + //超出新列表的长度,则加到最后面
  278 + if (fromIndex <= toListNewSize) {
  279 + toList.add(fromIndex, object);
  280 + }else{
  281 + toList.add(object);
273 } 282 }
274 iterator.remove(); 283 iterator.remove();
  284 + fromIndex = fromIndex + indexInterval;
  285 + if(indexInterval>1){
  286 + fromIndex = fromIndex + (int)(indexInterval * Math.random());
  287 + }else{
  288 + fromIndex = fromIndex + (Math.random()>0.5?1:0);
  289 + }
275 } 290 }
276 - return results;  
277 } 291 }
278 292
  293 + public static void main(String[] args) {
  294 + List<Integer> fromList = new ArrayList<>();
  295 + for (int index =1;index <=20;index ++){
  296 + fromList.add(index);
  297 + }
  298 +
  299 + List<Integer> toList = new ArrayList<>();
  300 + for (int index =0;index <100;index ++){
  301 + toList.add(0);
  302 + }
  303 + addByIndexIndex(fromList, toList, 1, 2, (value -> value%2==1));
  304 + System.out.println(toList);
  305 +// addByIndexIndex(fromList, toList, 4, 4, (value -> value%2==0));
  306 +// System.out.println(toList);
  307 + }
  308 +
  309 +
  310 +
279 } 311 }
  1 +package com.yoho.search.recall.scene.beans.cache;
  2 +
  3 +import com.yoho.search.base.utils.ISearchConstants;
  4 +import com.yoho.search.base.utils.ProductIndexEsField;
  5 +import com.yoho.search.core.es.model.SearchParam;
  6 +import com.yoho.search.core.es.model.SearchResult;
  7 +import com.yoho.search.recall.scene.beans.persional.PageProductIdBitSetComponent;
  8 +import com.yoho.search.recall.scene.beans.strategy.impls.RecommendSknStrategy;
  9 +import com.yoho.search.recall.scene.models.common.ParamQueryFilter;
  10 +import com.yoho.search.recall.scene.models.req.RecallRequest;
  11 +import com.yoho.search.recall.scene.models.req.RecallRequestResponse;
  12 +import com.yoho.search.recall.scene.models.req.RecallResponse;
  13 +import com.yoho.search.recall.scene.models.req.UserRecallRequest;
  14 +import com.yoho.search.service.base.SearchCommonService;
  15 +import org.apache.commons.collections.MapUtils;
  16 +import org.elasticsearch.index.query.BoolQueryBuilder;
  17 +import org.elasticsearch.index.query.QueryBuilders;
  18 +import org.springframework.beans.factory.annotation.Autowired;
  19 +import org.springframework.stereotype.Component;
  20 +
  21 +import java.util.*;
  22 +
  23 +@Component
  24 +public class SknRecallCacheBean{
  25 +
  26 + @Autowired
  27 + private SearchCommonService searchCommonService;
  28 + @Autowired
  29 + private PageProductIdBitSetComponent pageProductIdBitSetComponent;
  30 + @Autowired
  31 + private SknBaseInfoCacheBean sknBaseInfoCacheBean;
  32 +
  33 + /**
  34 + * 将推荐的skn构造成召回对象
  35 + *
  36 + * @return
  37 + */
  38 + public List<RecallRequestResponse> batchRecallRecommedSknList(UserRecallRequest userRecallRequest,List<Integer> recommedSknList,int maxReturnCount){
  39 + if(recommedSknList==null || recommedSknList.isEmpty()){
  40 + return new ArrayList<>();
  41 + }
  42 + List<Integer> filterSknList = this.filterRecommedSknList(userRecallRequest,recommedSknList,maxReturnCount);
  43 + return this.buildResults(userRecallRequest,filterSknList);
  44 + }
  45 +
  46 + private List<Integer> filterRecommedSknList(UserRecallRequest userRecallRequest, List<Integer> recommedSknList,int maxReturnCount){
  47 + if(recommedSknList==null || recommedSknList.isEmpty()){
  48 + return new ArrayList<>();
  49 + }
  50 + //1、构造searchParam
  51 + ParamQueryFilter paramQueryFilter = userRecallRequest.getParamQueryFilter();
  52 + SearchParam searchParam = new SearchParam();
  53 + searchParam.setQuery(paramQueryFilter.getParamQuery());
  54 + BoolQueryBuilder realFilter = QueryBuilders.boolQuery();
  55 + realFilter.must(paramQueryFilter.getParamFilter());
  56 + realFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.productSkn,recommedSknList));
  57 + searchParam.setFiter(realFilter);
  58 +
  59 + //2、设置分页参数
  60 + searchParam.setOffset(0);
  61 + searchParam.setSize(recommedSknList.size());
  62 + searchParam.setIncludeFields(Arrays.asList(ProductIndexEsField.productSkn));
  63 +
  64 + //3、执行查询
  65 + SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
  66 +
  67 + //4、构建已存在的skn结果
  68 + Set<Integer> existsProductSkns = new HashSet<>();
  69 + List<Map<String, Object>> productList = searchResult.getResultList();
  70 + for (Map<String, Object> productInfo : productList) {
  71 + Integer productSkn = MapUtils.getInteger(productInfo, ProductIndexEsField.productSkn, 0);
  72 + existsProductSkns.add(productSkn);
  73 + }
  74 +
  75 + //5、按顺序构造最终结果
  76 + List<Integer> results = new ArrayList<>();
  77 + for (Integer recommedSkn: recommedSknList) {
  78 + if(results.size()>=maxReturnCount){
  79 + continue;
  80 + }
  81 + if(existsProductSkns.contains(recommedSkn)){
  82 + results.add(recommedSkn);
  83 + }
  84 + }
  85 + return results;
  86 + }
  87 +
  88 + /**
  89 + * 将推荐的skn构造成召回对象
  90 + * @return
  91 + */
  92 + private List<RecallRequestResponse> buildResults(UserRecallRequest userRecallRequest,final List<Integer> recommedSknList){
  93 + List<RecallRequestResponse> results = new ArrayList<>();
  94 + if(recommedSknList==null || recommedSknList.isEmpty()){
  95 + return results;
  96 + }
  97 + ParamQueryFilter paramQueryFilter = userRecallRequest.getParamQueryFilter();
  98 + for (Integer recommendSkn : recommedSknList){
  99 + RecallRequest recallRequest = new RecallRequest(paramQueryFilter,new RecommendSknStrategy(recommendSkn));
  100 + RecallRequestResponse recallRequestResponse = new RecallRequestResponse(recallRequest);
  101 + recallRequestResponse.setResponse(new RecallResponse(1L, Arrays.asList(recommendSkn)),false);
  102 + results.add(recallRequestResponse);
  103 + }
  104 + return results;
  105 + }
  106 +
  107 +}
@@ -2,7 +2,6 @@ package com.yoho.search.recall.scene.beans.cache; @@ -2,7 +2,6 @@ package com.yoho.search.recall.scene.beans.cache;
2 2
3 import com.alibaba.fastjson.JSON; 3 import com.alibaba.fastjson.JSON;
4 import com.yoho.search.base.utils.CollectionUtils; 4 import com.yoho.search.base.utils.CollectionUtils;
5 -import com.yoho.search.core.es.utils.SearchParamUtils;  
6 import com.yoho.search.core.personalized.models.SortBrand; 5 import com.yoho.search.core.personalized.models.SortBrand;
7 import com.yoho.search.recall.scene.beans.builder.*; 6 import com.yoho.search.recall.scene.beans.builder.*;
8 import com.yoho.search.recall.scene.beans.persional.QueryUserPersionalFactorBean; 7 import com.yoho.search.recall.scene.beans.persional.QueryUserPersionalFactorBean;
@@ -25,7 +24,6 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us @@ -25,7 +24,6 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us
25 24
26 @Autowired 25 @Autowired
27 private QueryUserPersionalFactorBean queryUserPersionalFactorBean; 26 private QueryUserPersionalFactorBean queryUserPersionalFactorBean;
28 -  
29 @Autowired 27 @Autowired
30 private CommonRecallRequestBuilder commonRequestBuilder; 28 private CommonRecallRequestBuilder commonRequestBuilder;
31 @Autowired 29 @Autowired
@@ -33,7 +31,7 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us @@ -33,7 +31,7 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us
33 @Autowired 31 @Autowired
34 private BatchRecallCacheBean batchRecallCacheBean; 32 private BatchRecallCacheBean batchRecallCacheBean;
35 @Autowired 33 @Autowired
36 - private SknBaseInfoCacheBean sknBaseInfoCacheBean; 34 + private SknRecallCacheBean sknRecallCacheBean;
37 @Autowired 35 @Autowired
38 private RecallMergerResultBuilder recallMergerResultBuilder; 36 private RecallMergerResultBuilder recallMergerResultBuilder;
39 @Autowired 37 @Autowired
@@ -94,25 +92,26 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us @@ -94,25 +92,26 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us
94 //4、构造真实结果[排序,截取skn] 92 //4、构造真实结果[排序,截取skn]
95 begin = System.currentTimeMillis(); 93 begin = System.currentTimeMillis();
96 UserRecallResponse userRecallResponse = userRecallResponseBuilder.builderRecallResult(recallMergerResult, userRecallRequest, userPersonalFactor); 94 UserRecallResponse userRecallResponse = userRecallResponseBuilder.builderRecallResult(recallMergerResult, userRecallRequest, userPersonalFactor);
97 - RECALL_NEW_LOGGER.info("UserRecallRequestResponseCacheBean[3]-builderRecallResult,cost is [{}]", System.currentTimeMillis() - begin); 95 + RECALL_NEW_LOGGER.info("UserRecallRequestResponseCacheBean[4]-builderRecallResult,cost is [{}]", System.currentTimeMillis() - begin);
98 return userRecallResponse; 96 return userRecallResponse;
99 } 97 }
100 98
101 private List<RecallRequestResponse> batchRecall(UserRecallRequest userRecallRequest,UserPersonalFactor userPersonalFactor) { 99 private List<RecallRequestResponse> batchRecall(UserRecallRequest userRecallRequest,UserPersonalFactor userPersonalFactor) {
102 - long begin = System.currentTimeMillis();  
103 -  
104 //1、构造批量请求并召回 100 //1、构造批量请求并召回
  101 + long begin = System.currentTimeMillis();
105 List<RecallRequest> batchRecallRequests = this.buildBatchRecallRequests(userRecallRequest, userPersonalFactor); 102 List<RecallRequest> batchRecallRequests = this.buildBatchRecallRequests(userRecallRequest, userPersonalFactor);
106 List<RecallRequestResponse> batchRecallRequestResponses = batchRecallCacheBean.batchRecallAndCache(batchRecallRequests); 103 List<RecallRequestResponse> batchRecallRequestResponses = batchRecallCacheBean.batchRecallAndCache(batchRecallRequests);
107 RECALL_NEW_LOGGER.info("UserRecallRequestResponseCacheBean[2]-batchRecallRequestResponses,cost is [{}]", System.currentTimeMillis() - begin); 104 RECALL_NEW_LOGGER.info("UserRecallRequestResponseCacheBean[2]-batchRecallRequestResponses,cost is [{}]", System.currentTimeMillis() - begin);
108 105
109 - //2、根据推荐的skn直接构造结果  
110 - List<RecallRequestResponse> recommendSknRequestResponses = this.buildRecommendSknRequestResponses(userPersonalFactor); 106 + //2、根据推荐的skn构造结果
  107 + begin = System.currentTimeMillis();
  108 + List<RecallRequestResponse> recommendSknRequestResponses = sknRecallCacheBean.batchRecallRecommedSknList(userRecallRequest,userPersonalFactor.getRecommendSknList(),8);
  109 + RECALL_NEW_LOGGER.info("UserRecallRequestResponseCacheBean[3]-batchRecallRecommedSknList,cost is [{}]", System.currentTimeMillis() - begin);
111 110
112 //3、构造最终返回结果 111 //3、构造最终返回结果
113 List<RecallRequestResponse> batchRequestResults = new ArrayList<>(); 112 List<RecallRequestResponse> batchRequestResults = new ArrayList<>();
  113 + batchRequestResults.addAll(recommendSknRequestResponses);//推荐的skn要保证有序,所以放前面
114 batchRequestResults.addAll(batchRecallRequestResponses); 114 batchRequestResults.addAll(batchRecallRequestResponses);
115 - batchRequestResults.addAll(recommendSknRequestResponses);  
116 115
117 //4、日志打印 116 //4、日志打印
118 if (userRecallRequest.openDetailLog()) { 117 if (userRecallRequest.openDetailLog()) {
@@ -121,9 +120,6 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us @@ -121,9 +120,6 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us
121 RecallResponse recallRespone = recallRequestResponse.getResponse(); 120 RecallResponse recallRespone = recallRequestResponse.getResponse();
122 StringBuilder responseValue = new StringBuilder(); 121 StringBuilder responseValue = new StringBuilder();
123 responseValue.append(recallRespone==null?"null":JSON.toJSONString(recallRespone)); 122 responseValue.append(recallRespone==null?"null":JSON.toJSONString(recallRespone));
124 -// if(recallRespone!=null && (recallRespone.getSkns()==null || recallRespone.getSkns().isEmpty())){  
125 -// responseValue.append(",dsl is [").append(SearchParamUtils.genSearchSourceBuilderFromSearchParam(recallRequest.searchParam()).toString());  
126 -// }  
127 RECALL_NEW_LOGGER.info("request_type is [{}], response is [{}] ", recallRequest.requestStrategy().name(),responseValue.toString()); 123 RECALL_NEW_LOGGER.info("request_type is [{}], response is [{}] ", recallRequest.requestStrategy().name(),responseValue.toString());
128 } 124 }
129 } 125 }
@@ -174,24 +170,4 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us @@ -174,24 +170,4 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us
174 return CollectionUtils.safeSubList(results, 0, maxCount); 170 return CollectionUtils.safeSubList(results, 0, maxCount);
175 } 171 }
176 172
177 - /**  
178 - * 将推荐的skn构造成召回对象  
179 - * @param userPersonalFactor  
180 - * @return  
181 - */  
182 - private List<RecallRequestResponse> buildRecommendSknRequestResponses(UserPersonalFactor userPersonalFactor){  
183 - List<RecallRequestResponse> results = new ArrayList<>();  
184 - List<Integer> recommendSkns = userPersonalFactor.getRecommendSknList();  
185 - if(recommendSkns==null || recommendSkns.isEmpty()){  
186 - return results;  
187 - }  
188 - for (Integer recommendSkn : recommendSkns){  
189 - RecallRequest recallRequest = new RecallRequest(new RecommendSknStrategy(recommendSkn));  
190 - RecallRequestResponse recallRequestResponse = new RecallRequestResponse(recallRequest);  
191 - recallRequestResponse.setResponse(new RecallResponse(1L,Arrays.asList(recommendSkn)),false);  
192 - results.add(recallRequestResponse);  
193 - }  
194 - return results;  
195 - }  
196 -  
197 } 173 }
1 package com.yoho.search.recall.scene.beans.persional; 1 package com.yoho.search.recall.scene.beans.persional;
2 2
  3 +import com.alibaba.fastjson.JSON;
  4 +import com.alibaba.fastjson.JSONObject;
3 import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder; 5 import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
4 import com.yoho.search.common.cache.impls.EhCache; 6 import com.yoho.search.common.cache.impls.EhCache;
  7 +import com.yoho.search.common.cache.impls.SearchRedis;
5 import com.yoho.search.common.cache.model.CacheObject; 8 import com.yoho.search.common.cache.model.CacheObject;
6 import com.yoho.search.recall.scene.models.common.ParamQueryFilter; 9 import com.yoho.search.recall.scene.models.common.ParamQueryFilter;
7 import org.slf4j.Logger; 10 import org.slf4j.Logger;
@@ -13,43 +16,58 @@ import java.util.concurrent.ConcurrentHashMap; @@ -13,43 +16,58 @@ import java.util.concurrent.ConcurrentHashMap;
13 import java.util.concurrent.ExecutorService; 16 import java.util.concurrent.ExecutorService;
14 import java.util.concurrent.Executors; 17 import java.util.concurrent.Executors;
15 18
16 -public abstract class AbstractPageComponent { 19 +public abstract class AbstractPageComponent<T> {
17 20
18 private static final Logger logger = LoggerFactory.getLogger(AbstractPageComponent.class); 21 private static final Logger logger = LoggerFactory.getLogger(AbstractPageComponent.class);
19 22
20 @Autowired 23 @Autowired
21 private EhCache ehCache; 24 private EhCache ehCache;
  25 + @Autowired
  26 + private SearchRedis searchRedis;
22 27
23 private ConcurrentHashMap<String, Integer> mapLock; 28 private ConcurrentHashMap<String, Integer> mapLock;
24 private ExecutorService executorService; 29 private ExecutorService executorService;
25 30
  31 + private boolean synchronous = true;//是否同步
  32 +
26 @PostConstruct 33 @PostConstruct
27 void init() { 34 void init() {
28 mapLock = new ConcurrentHashMap(20);//使用一个Map来限流 35 mapLock = new ConcurrentHashMap(20);//使用一个Map来限流
29 executorService = Executors.newFixedThreadPool(5); 36 executorService = Executors.newFixedThreadPool(5);
30 } 37 }
31 38
32 - public Object queryWithCache(ParamQueryFilter paramQueryFilter) { 39 + public T queryWithCache(ParamQueryFilter paramQueryFilter, Class<T> clazz) {
33 //1、生成RedisKeyBuilder 40 //1、生成RedisKeyBuilder
34 RedisKeyBuilder redisKeyBuilder = this.genRedisKeyBuilder(paramQueryFilter); 41 RedisKeyBuilder redisKeyBuilder = this.genRedisKeyBuilder(paramQueryFilter);
35 if (redisKeyBuilder == null) { 42 if (redisKeyBuilder == null) {
36 return null; 43 return null;
37 } 44 }
38 - //2、缓存命中,则直接返回  
39 - CacheObject cacheObject = ehCache.get(redisKeyBuilder);  
40 - if (cacheObject != null) {  
41 - return cacheObject.toObject(); 45 + //2、取本地缓存,缓存命中,则直接返回
  46 + T result = this.getJavaObjectFromEhcache(redisKeyBuilder);
  47 + if (result != null) {
  48 + return result;
  49 + }
  50 + //3、取redis缓存,缓存命中,则回写ehcahce
  51 + result = this.getJavaObjectFromRedis(redisKeyBuilder,clazz);
  52 + if (result != null) {
  53 + this.addJavaObjectToEhcache(redisKeyBuilder,result);
  54 + return result;
  55 + }
  56 +
  57 + //4、如果是同步查询,则直接调子类方法查询
  58 + if (synchronous) {
  59 + return this.doInnerQuery(redisKeyBuilder,paramQueryFilter);
42 } 60 }
43 - //3、限流判断以及重复请求预防 61 +
  62 + //5、执行异步流程
44 if (mapLock.size() > 20 || mapLock.putIfAbsent(redisKeyBuilder.getKey(), 1) != null) { 63 if (mapLock.size() > 20 || mapLock.putIfAbsent(redisKeyBuilder.getKey(), 1) != null) {
45 return null; 64 return null;
46 } 65 }
47 - //4、异步执行查询并加入缓存 66 +
  67 + //6、异步执行查询并加入缓存
48 executorService.submit(() -> { 68 executorService.submit(() -> {
49 try { 69 try {
50 - Object queryResult = doRealQuery(paramQueryFilter);  
51 - CacheObject toCacheResult = new CacheObject(queryResult);  
52 - ehCache.addOrUpdate(redisKeyBuilder, toCacheResult, this.cacheTimeInSecond() / 60); 70 + this.doInnerQuery(redisKeyBuilder,paramQueryFilter);
53 } catch (Exception e) { 71 } catch (Exception e) {
54 logger.error(e.getMessage(), e); 72 logger.error(e.getMessage(), e);
55 } finally { 73 } finally {
@@ -59,10 +77,46 @@ public abstract class AbstractPageComponent { @@ -59,10 +77,46 @@ public abstract class AbstractPageComponent {
59 return null; 77 return null;
60 } 78 }
61 79
  80 + private T getJavaObjectFromEhcache(RedisKeyBuilder redisKeyBuilder){
  81 + CacheObject cacheObject = ehCache.get(redisKeyBuilder);
  82 + if (cacheObject != null) {
  83 + return (T)cacheObject.toObject();
  84 + }
  85 + return null;
  86 + }
  87 +
  88 + private void addJavaObjectToEhcache(RedisKeyBuilder redisKeyBuilder,T result){
  89 + ehCache.addOrUpdate(redisKeyBuilder, new CacheObject(result), this.cacheTimeInSecond() / 60);
  90 + }
  91 +
  92 + private T getJavaObjectFromRedis(RedisKeyBuilder redisKeyBuilder,Class<T> clazz){
  93 + CacheObject cacheObject = searchRedis.get(redisKeyBuilder);
  94 + if (cacheObject == null) {
  95 + return null;
  96 + }
  97 + JSONObject jsonObject = cacheObject.toJSONObject();
  98 + T result = JSON.toJavaObject(jsonObject, clazz);
  99 + return result;
  100 + }
  101 +
  102 + private void addJavaObjectToRedis(RedisKeyBuilder redisKeyBuilder,T result){
  103 + JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(result));
  104 + CacheObject toCacheResult = new CacheObject(jsonObject);
  105 + searchRedis.addOrUpdate(redisKeyBuilder, toCacheResult, this.cacheTimeInSecond() / 60);
  106 + }
  107 +
  108 + private T doInnerQuery(RedisKeyBuilder redisKeyBuilder, ParamQueryFilter paramQueryFilter) {
  109 + T queryResult = doRealQuery(paramQueryFilter);
  110 + JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(queryResult));
  111 + CacheObject toCacheResult = new CacheObject(jsonObject);
  112 + searchRedis.addOrUpdate(redisKeyBuilder, toCacheResult, this.cacheTimeInSecond() / 60);
  113 + return queryResult;
  114 + }
  115 +
62 protected abstract RedisKeyBuilder genRedisKeyBuilder(ParamQueryFilter paramQueryFilter); 116 protected abstract RedisKeyBuilder genRedisKeyBuilder(ParamQueryFilter paramQueryFilter);
63 117
64 protected abstract int cacheTimeInSecond(); 118 protected abstract int cacheTimeInSecond();
65 119
66 - protected abstract Object doRealQuery(ParamQueryFilter paramQueryFilter); 120 + protected abstract T doRealQuery(ParamQueryFilter paramQueryFilter);
67 121
68 } 122 }
@@ -25,7 +25,7 @@ import org.springframework.stereotype.Component; @@ -25,7 +25,7 @@ import org.springframework.stereotype.Component;
25 import java.util.*; 25 import java.util.*;
26 26
27 @Component 27 @Component
28 -public class PagePersionalFactorComponent extends AbstractPageComponent { 28 +public class PagePersionalFactorComponent extends AbstractPageComponent<PagePersonalFactor> {
29 29
30 @Autowired 30 @Autowired
31 private SearchCommonService searchCommonService; 31 private SearchCommonService searchCommonService;
@@ -36,7 +36,7 @@ public class PagePersionalFactorComponent extends AbstractPageComponent { @@ -36,7 +36,7 @@ public class PagePersionalFactorComponent extends AbstractPageComponent {
36 * @return 36 * @return
37 */ 37 */
38 public PagePersonalFactor queryPagePersionalFactor(ParamQueryFilter paramQueryFilter) { 38 public PagePersonalFactor queryPagePersionalFactor(ParamQueryFilter paramQueryFilter) {
39 - Object value = super.queryWithCache(paramQueryFilter); 39 + Object value = super.queryWithCache(paramQueryFilter,PagePersonalFactor.class);
40 return value==null?null:(PagePersonalFactor)value; 40 return value==null?null:(PagePersonalFactor)value;
41 } 41 }
42 42
@@ -51,7 +51,7 @@ public class PagePersionalFactorComponent extends AbstractPageComponent { @@ -51,7 +51,7 @@ public class PagePersionalFactorComponent extends AbstractPageComponent {
51 } 51 }
52 52
53 @Override 53 @Override
54 - protected Object doRealQuery(ParamQueryFilter paramQueryFilter) { 54 + protected PagePersonalFactor doRealQuery(ParamQueryFilter paramQueryFilter) {
55 //1、构造参数 55 //1、构造参数
56 SearchParam searchParam = new SearchParam(); 56 SearchParam searchParam = new SearchParam();
57 searchParam.setQuery(paramQueryFilter.getParamQuery()); 57 searchParam.setQuery(paramQueryFilter.getParamQuery());
1 package com.yoho.search.recall.scene.beans.persional; 1 package com.yoho.search.recall.scene.beans.persional;
2 2
  3 +import com.alibaba.fastjson.JSON;
3 import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder; 4 import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
4 import com.yoho.search.base.utils.ISearchConstants; 5 import com.yoho.search.base.utils.ISearchConstants;
5 import com.yoho.search.base.utils.ProductIndexEsField; 6 import com.yoho.search.base.utils.ProductIndexEsField;
@@ -19,6 +20,7 @@ import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation; @@ -19,6 +20,7 @@ import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation;
19 import org.elasticsearch.search.aggregations.bucket.terms.Terms; 20 import org.elasticsearch.search.aggregations.bucket.terms.Terms;
20 import org.springframework.beans.factory.annotation.Autowired; 21 import org.springframework.beans.factory.annotation.Autowired;
21 import org.springframework.stereotype.Component; 22 import org.springframework.stereotype.Component;
  23 +import sun.applet.Main;
22 24
23 import java.util.ArrayList; 25 import java.util.ArrayList;
24 import java.util.Iterator; 26 import java.util.Iterator;
@@ -26,7 +28,7 @@ import java.util.List; @@ -26,7 +28,7 @@ import java.util.List;
26 import java.util.Map; 28 import java.util.Map;
27 29
28 @Component 30 @Component
29 -public class PageProductIdBitSetComponent extends AbstractPageComponent { 31 +public class PageProductIdBitSetComponent extends AbstractPageComponent<PageProductIdBitSet>{
30 32
31 @Autowired 33 @Autowired
32 private SearchCommonService searchCommonService; 34 private SearchCommonService searchCommonService;
@@ -38,8 +40,10 @@ public class PageProductIdBitSetComponent extends AbstractPageComponent { @@ -38,8 +40,10 @@ public class PageProductIdBitSetComponent extends AbstractPageComponent {
38 * @return 40 * @return
39 */ 41 */
40 public PageProductIdBitSet queryPageProductIdBitSet(ParamQueryFilter paramQueryFilter) { 42 public PageProductIdBitSet queryPageProductIdBitSet(ParamQueryFilter paramQueryFilter) {
41 - Object value = super.queryWithCache(paramQueryFilter);  
42 - return value == null ? null : (PageProductIdBitSet) value; 43 + //Object value = super.queryWithCache(paramQueryFilter);
  44 + //return value == null ? null : (PageProductIdBitSet) value;
  45 + //return doRealQuery(paramQueryFilter);
  46 + return null;
43 } 47 }
44 48
45 @Override 49 @Override
@@ -53,7 +57,7 @@ public class PageProductIdBitSetComponent extends AbstractPageComponent { @@ -53,7 +57,7 @@ public class PageProductIdBitSetComponent extends AbstractPageComponent {
53 } 57 }
54 58
55 @Override 59 @Override
56 - protected Object doRealQuery(ParamQueryFilter paramQueryFilter) { 60 + protected PageProductIdBitSet doRealQuery(ParamQueryFilter paramQueryFilter) {
57 //1、构造请求参数 61 //1、构造请求参数
58 SearchParam searchParam = new SearchParam(); 62 SearchParam searchParam = new SearchParam();
59 searchParam.setQuery(paramQueryFilter.getParamQuery()); 63 searchParam.setQuery(paramQueryFilter.getParamQuery());
@@ -98,5 +102,4 @@ public class PageProductIdBitSetComponent extends AbstractPageComponent { @@ -98,5 +102,4 @@ public class PageProductIdBitSetComponent extends AbstractPageComponent {
98 return pageProductIdBitSet; 102 return pageProductIdBitSet;
99 } 103 }
100 104
101 -  
102 } 105 }
@@ -32,10 +32,6 @@ public class QueryUserPersionalFactorBean { @@ -32,10 +32,6 @@ public class QueryUserPersionalFactorBean {
32 private UserPersionalFactorComponent userComponent; 32 private UserPersionalFactorComponent userComponent;
33 @Autowired 33 @Autowired
34 private SearchDynamicConfigService searchDynamicConfigService; 34 private SearchDynamicConfigService searchDynamicConfigService;
35 - @Autowired  
36 - private PageProductIdBitSetComponent pageProductIdBitSetComponent;  
37 - @Autowired  
38 - private SknBaseInfoCacheBean sknBaseInfoCacheBean;  
39 35
40 /** 36 /**
41 * 获取个性化因子 37 * 获取个性化因子
@@ -59,32 +55,20 @@ public class QueryUserPersionalFactorBean { @@ -59,32 +55,20 @@ public class QueryUserPersionalFactorBean {
59 long cost = System.currentTimeMillis() - begin; 55 long cost = System.currentTimeMillis() - begin;
60 RECALL_NEW_LOGGER.info("QueryUserPersionalFactor[1]:queryPageFactor. uid is[{}],udid is[{}], cost is[{}],size is[{}] ",uid, udid,cost,pageFactor==null ?"null":pageFactor.pageBrandSortsSize()); 56 RECALL_NEW_LOGGER.info("QueryUserPersionalFactor[1]:queryPageFactor. uid is[{}],udid is[{}], cost is[{}],size is[{}] ",uid, udid,cost,pageFactor==null ?"null":pageFactor.pageBrandSortsSize());
61 57
62 - //2、获取页面上的product bitset  
63 - PageProductIdBitSet pageProductIdBitSet = pageProductIdBitSetComponent.queryPageProductIdBitSet(userRecallRequest.getParamQueryFilter());  
64 - cost = System.currentTimeMillis() - begin;  
65 - RECALL_NEW_LOGGER.info("QueryUserPersionalFactor[2]:queryPageSknBitSet. uid is[{}],udid is[{}], cost is[{}], cardinality is[{}] ",uid, udid,cost, pageProductIdBitSet ==null?"null":pageProductIdBitSet.getCardinality());  
66 -  
67 - //3、边界值判断  
68 - if(pageFactor==null && pageProductIdBitSet==null){  
69 - return new UserPersonalFactor();  
70 - }  
71 -  
72 - //4、获取用户的个性化因子 58 + //2、获取用户的个性化因子
73 begin = System.currentTimeMillis(); 59 begin = System.currentTimeMillis();
74 UserPersonalFactorRspNew userFactor = userComponent.queryUserPersionalFactor(userRecallRequest.getUid(), userRecallRequest.getUdid()); 60 UserPersonalFactorRspNew userFactor = userComponent.queryUserPersionalFactor(userRecallRequest.getUid(), userRecallRequest.getUdid());
75 - if(userFactor==null){  
76 - userFactor = this.buildDefaultUserPersonalFactorRspNew(pageFactor);  
77 - }  
78 cost = System.currentTimeMillis() - begin; 61 cost = System.currentTimeMillis() - begin;
79 int userSortBrandSize = userFactor.getSortBrandList().size(); 62 int userSortBrandSize = userFactor.getSortBrandList().size();
80 int userRealSortBrandSize = userFactor.getRealTimeSortBrandList().size(); 63 int userRealSortBrandSize = userFactor.getRealTimeSortBrandList().size();
  64 + int recommendSknSize = userFactor.getRecommendSknList().size();
81 if (!openDetailLog) { 65 if (!openDetailLog) {
82 - RECALL_NEW_LOGGER.info("QueryUserPersionalFactor[2]:queryUserFactor. uid is[{}],udid is[{}], cost is[{}], sortBrand size is[{}],userRealSortBrandSize is[{}] ", uid ,udid, cost, userSortBrandSize,userRealSortBrandSize); 66 + RECALL_NEW_LOGGER.info("QueryUserPersionalFactor[2]:queryUserFactor. uid is[{}],udid is[{}], cost is[{}], sortBrand size is[{}],userRealSortBrandSize is[{}],recommendSknSize is[{}] ", uid ,udid, cost, userSortBrandSize,userRealSortBrandSize,recommendSknSize);
83 } else { 67 } else {
84 - RECALL_NEW_LOGGER.info("QueryUserPersionalFactor[2]:queryUserFactor. uid is[{}],udid is[{}], cost is[{}],sortBrand size is[{}] , userRealSortBrandSize is[{}] , userFactor is[{}] ",uid,udid, cost,userSortBrandSize,userRealSortBrandSize,JSON.toJSONString(userFactor)); 68 + RECALL_NEW_LOGGER.info("QueryUserPersionalFactor[2]:queryUserFactor. uid is[{}],udid is[{}], cost is[{}],sortBrand size is[{}] , userRealSortBrandSize is[{}] ,recommendSknSize is[{}], userFactor is[{}] ",uid,udid, cost,userSortBrandSize,userRealSortBrandSize,recommendSknSize,JSON.toJSONString(userFactor));
85 } 69 }
86 //5、构造结果 70 //5、构造结果
87 - UserPersonalFactor userPersonalFactor = this.buildUserPersonalFactor(pageFactor,userFactor, pageProductIdBitSet); 71 + UserPersonalFactor userPersonalFactor = this.buildUserPersonalFactor(pageFactor,userFactor);
88 if(!openDetailLog){ 72 if(!openDetailLog){
89 RECALL_NEW_LOGGER.info("QueryUserPersionalFactor[3]:after join. uid is[{}],udid is[{}], forecastSortBrand size is[{}], realTimeSortBrand size is[{}], sortPriceAreas size is [{}] ", uid,udid, userPersonalFactor.getForecastSortBrandListSize(),userPersonalFactor.getRealTimeSortBrandListSize(),userPersonalFactor.getSortPriceAreasListSize()); 73 RECALL_NEW_LOGGER.info("QueryUserPersionalFactor[3]:after join. uid is[{}],udid is[{}], forecastSortBrand size is[{}], realTimeSortBrand size is[{}], sortPriceAreas size is [{}] ", uid,udid, userPersonalFactor.getForecastSortBrandListSize(),userPersonalFactor.getRealTimeSortBrandListSize(),userPersonalFactor.getSortPriceAreasListSize());
90 }else{ 74 }else{
@@ -122,7 +106,7 @@ public class QueryUserPersionalFactorBean { @@ -122,7 +106,7 @@ public class QueryUserPersionalFactorBean {
122 return new UserPersonalFactorRspNew(sortBrandList, new ArrayList<>(), sortPriceAreasList,new ArrayList<>(), ""); 106 return new UserPersonalFactorRspNew(sortBrandList, new ArrayList<>(), sortPriceAreasList,new ArrayList<>(), "");
123 } 107 }
124 108
125 - private UserPersonalFactor buildUserPersonalFactor(PagePersonalFactor pageFactor,UserPersonalFactorRspNew userFactor,PageProductIdBitSet pageProductIdBitSet){ 109 + private UserPersonalFactor buildUserPersonalFactor(PagePersonalFactor pageFactor,UserPersonalFactorRspNew userFactor){
126 //1、构造页面中的品牌品类map 110 //1、构造页面中的品牌品类map
127 Map<Integer, List<Integer>> pageBrand2MiSortIdsMap = this.getPageBrand2MiSortIdsMap(pageFactor); 111 Map<Integer, List<Integer>> pageBrand2MiSortIdsMap = this.getPageBrand2MiSortIdsMap(pageFactor);
128 //2、构造实时【品类+品牌】 112 //2、构造实时【品类+品牌】
@@ -132,9 +116,9 @@ public class QueryUserPersionalFactorBean { @@ -132,9 +116,9 @@ public class QueryUserPersionalFactorBean {
132 int maxForecastSortBrandCount = searchDynamicConfigService.maxForecastSortBrandCount(); 116 int maxForecastSortBrandCount = searchDynamicConfigService.maxForecastSortBrandCount();
133 List<SortBrand> forecastSortBrandList = this.getSortBrandListWithSort(pageBrand2MiSortIdsMap, userFactor.getSortBrandList(),maxForecastSortBrandCount); 117 List<SortBrand> forecastSortBrandList = this.getSortBrandListWithSort(pageBrand2MiSortIdsMap, userFactor.getSortBrandList(),maxForecastSortBrandCount);
134 //4、构造品类价格带 118 //4、构造品类价格带
135 - List<SortPriceAreas> sortPriceAreasList = this.getSortPriceAreasListWithSort(pageFactor, userFactor); 119 + List<SortPriceAreas> sortPriceAreasList = this.getSortPriceAreasListWithSort(userFactor,pageFactor);
136 //5、构造推荐的skn列表 120 //5、构造推荐的skn列表
137 - List<Integer> recommendSknList = this.getRecommendSknList(pageProductIdBitSet, userFactor); 121 + List<Integer> recommendSknList = userFactor.getRecommendSknList();
138 //6、返回最终结果 122 //6、返回最终结果
139 return new UserPersonalFactor(realTimeSortBrandList,forecastSortBrandList, sortPriceAreasList,recommendSknList,userFactor.getVector()); 123 return new UserPersonalFactor(realTimeSortBrandList,forecastSortBrandList, sortPriceAreasList,recommendSknList,userFactor.getVector());
140 } 124 }
@@ -180,7 +164,7 @@ public class QueryUserPersionalFactorBean { @@ -180,7 +164,7 @@ public class QueryUserPersionalFactorBean {
180 * @param userFactorNew 164 * @param userFactorNew
181 * @return 165 * @return
182 */ 166 */
183 - private List<SortPriceAreas> getSortPriceAreasListWithSort(PagePersonalFactor pageFactor, UserPersonalFactorRspNew userFactorNew) { 167 + private List<SortPriceAreas> getSortPriceAreasListWithSort(UserPersonalFactorRspNew userFactorNew,PagePersonalFactor pageFactor) {
184 List<SortPriceAreas> sortPriceAreas = userFactorNew.getSortPriceAreasList(); 168 List<SortPriceAreas> sortPriceAreas = userFactorNew.getSortPriceAreasList();
185 if (sortPriceAreas == null || sortPriceAreas.isEmpty()) { 169 if (sortPriceAreas == null || sortPriceAreas.isEmpty()) {
186 return new ArrayList<>(); 170 return new ArrayList<>();
@@ -188,43 +172,4 @@ public class QueryUserPersionalFactorBean { @@ -188,43 +172,4 @@ public class QueryUserPersionalFactorBean {
188 return sortPriceAreas; 172 return sortPriceAreas;
189 } 173 }
190 174
191 - private List<Integer> getRecommendSknList(PageProductIdBitSet pageProductIdBitSet, UserPersonalFactorRspNew userFactor){  
192 - List<Integer> sknResults = new ArrayList<>();  
193 - if(pageProductIdBitSet ==null ){  
194 - return sknResults;  
195 - }  
196 - List<Integer> recommendSknList = userFactor.getRecommendSknList();  
197 - if(recommendSknList==null || recommendSknList.isEmpty()){  
198 - //recommendSknList = this.genRandomRecommendSknList(100);//随机构造SKN  
199 - return new ArrayList<>();  
200 - }  
201 - Map<Integer, Integer> sknToProductIdMap = sknBaseInfoCacheBean.queryProductSknToProductIdMap(recommendSknList);  
202 - for (Integer productSkn : recommendSknList){  
203 - Integer productId = sknToProductIdMap.get(productSkn);  
204 - if(productId==null){  
205 - continue;  
206 - }  
207 - if(pageProductIdBitSet.exist(productId)){  
208 - sknResults.add(productSkn);  
209 - }  
210 - }  
211 - return sknResults;  
212 - }  
213 -  
214 - private List<Integer> genRandomRecommendSknList(int count){  
215 - List<Integer> randomRecommendSknList = new ArrayList<>();  
216 - randomRecommendSknList.add(512588092);  
217 - randomRecommendSknList.add(512588098);  
218 - randomRecommendSknList.add(51158451);  
219 - randomRecommendSknList.add(51088211);  
220 - randomRecommendSknList.add(51158004);  
221 -  
222 - randomRecommendSknList.add(51131787);  
223 - randomRecommendSknList.add(51085410);  
224 - randomRecommendSknList.add(51158453);  
225 - randomRecommendSknList.add(51158450);  
226 - randomRecommendSknList.add(51095539);  
227 - return randomRecommendSknList;  
228 - }  
229 -  
230 } 175 }
@@ -42,7 +42,7 @@ public class UserPersionalFactorComponent { @@ -42,7 +42,7 @@ public class UserPersionalFactorComponent {
42 JSONObject userPersonalFactorRspJSon = result.getJSONObject("data"); 42 JSONObject userPersonalFactorRspJSon = result.getJSONObject("data");
43 UserPersonalFactorRspNew rsp = JSON.toJavaObject(userPersonalFactorRspJSon, UserPersonalFactorRspNew.class); 43 UserPersonalFactorRspNew rsp = JSON.toJavaObject(userPersonalFactorRspJSon, UserPersonalFactorRspNew.class);
44 if (rsp == null) { 44 if (rsp == null) {
45 - return new UserPersonalFactorRspNew(); 45 + rsp = new UserPersonalFactorRspNew();
46 } 46 }
47 if(rsp.getSortBrandList()==null){ 47 if(rsp.getSortBrandList()==null){
48 rsp.setSortBrandList(new ArrayList<>()); 48 rsp.setSortBrandList(new ArrayList<>());
@@ -56,7 +56,7 @@ public class UserPersionalFactorComponent { @@ -56,7 +56,7 @@ public class UserPersionalFactorComponent {
56 return rsp; 56 return rsp;
57 } catch (Exception e) { 57 } catch (Exception e) {
58 RECALL_NEW_LOGGER.error(e.getMessage(), e); 58 RECALL_NEW_LOGGER.error(e.getMessage(), e);
59 - return null; 59 + return new UserPersonalFactorRspNew();
60 } 60 }
61 } 61 }
62 62
1 package com.yoho.search.recall.scene.beans.strategy.impls; 1 package com.yoho.search.recall.scene.beans.strategy.impls;
2 2
3 -import com.alibaba.fastjson.JSON;  
4 import com.yoho.search.recall.scene.beans.helper.ExtendFilterHelper; 3 import com.yoho.search.recall.scene.beans.helper.ExtendFilterHelper;
5 import com.yoho.search.recall.scene.beans.helper.SortBuilderHelper; 4 import com.yoho.search.recall.scene.beans.helper.SortBuilderHelper;
6 import com.yoho.search.recall.scene.beans.strategy.IStrategy; 5 import com.yoho.search.recall.scene.beans.strategy.IStrategy;
@@ -9,8 +8,6 @@ import com.yoho.search.recall.scene.constants.CacheTimeConstants; @@ -9,8 +8,6 @@ import com.yoho.search.recall.scene.constants.CacheTimeConstants;
9 import org.elasticsearch.index.query.QueryBuilder; 8 import org.elasticsearch.index.query.QueryBuilder;
10 import org.elasticsearch.search.sort.SortBuilder; 9 import org.elasticsearch.search.sort.SortBuilder;
11 10
12 -import java.util.List;  
13 -  
14 /** 11 /**
15 * 推荐skn的召回策略 12 * 推荐skn的召回策略
16 * 13 *
@@ -47,7 +44,7 @@ public class RecommendSknStrategy implements IStrategy { @@ -47,7 +44,7 @@ public class RecommendSknStrategy implements IStrategy {
47 44
48 @Override 45 @Override
49 public int cacheTimeInSecond() { 46 public int cacheTimeInSecond() {
50 - return CacheTimeConstants.COMMON_RECALL_STRATEGY_CACHE_TIME; 47 + return CacheTimeConstants.RECOMMEND_SKN_CACHE_TIME;
51 } 48 }
52 49
53 @Override 50 @Override
@@ -57,4 +54,7 @@ public class RecommendSknStrategy implements IStrategy { @@ -57,4 +54,7 @@ public class RecommendSknStrategy implements IStrategy {
57 return sb.toString(); 54 return sb.toString();
58 } 55 }
59 56
  57 + public Integer getRecommendSkn() {
  58 + return recommendSkn;
  59 + }
60 } 60 }
@@ -9,6 +9,9 @@ public class CacheTimeConstants { @@ -9,6 +9,9 @@ public class CacheTimeConstants {
9 //通用召回的缓存 - 10分钟 9 //通用召回的缓存 - 10分钟
10 public static final int COMMON_RECALL_STRATEGY_CACHE_TIME = 10 * 60; 10 public static final int COMMON_RECALL_STRATEGY_CACHE_TIME = 10 * 60;
11 11
  12 + //SKN的的缓存 - 60分钟
  13 + public static final int RECOMMEND_SKN_CACHE_TIME = 60 * 60;
  14 +
12 //品类+品牌的缓存 - 60分钟 15 //品类+品牌的缓存 - 60分钟
13 public static final int SORT_BRAND_RECALL_STRATEGY_CACHE_TIME = 60 * 60; 16 public static final int SORT_BRAND_RECALL_STRATEGY_CACHE_TIME = 60 * 60;
14 17
@@ -3,6 +3,7 @@ package com.yoho.search.recall.scene.models.common; @@ -3,6 +3,7 @@ package com.yoho.search.recall.scene.models.common;
3 3
4 import com.yoho.search.base.utils.ProductIndexEsField; 4 import com.yoho.search.base.utils.ProductIndexEsField;
5 import com.yoho.search.core.es.model.SearchParam; 5 import com.yoho.search.core.es.model.SearchParam;
  6 +import com.yoho.search.recall.scene.beans.strategy.IStrategy;
6 import com.yoho.search.recall.scene.beans.strategy.StrategyEnum; 7 import com.yoho.search.recall.scene.beans.strategy.StrategyEnum;
7 8
8 import java.util.Arrays; 9 import java.util.Arrays;
@@ -14,7 +15,7 @@ public interface IRecallRequest { @@ -14,7 +15,7 @@ public interface IRecallRequest {
14 * 查询类型 15 * 查询类型
15 * @return 16 * @return
16 */ 17 */
17 - StrategyEnum requestStrategy(); 18 + IStrategy strategy();
18 19
19 /** 20 /**
20 * 真实的查询参数 21 * 真实的查询参数
@@ -30,7 +30,7 @@ public class RecallMergerResult { @@ -30,7 +30,7 @@ public class RecallMergerResult {
30 public static class SknResult { 30 public static class SknResult {
31 31
32 private Integer productSkn; 32 private Integer productSkn;
33 - private List<StrategyEnum> strategys; 33 + private StrategyEnum strategy;
34 34
35 private Integer brandId; 35 private Integer brandId;
36 private Integer middleSortId; 36 private Integer middleSortId;
@@ -53,8 +53,8 @@ public class RecallMergerResult { @@ -53,8 +53,8 @@ public class RecallMergerResult {
53 this.factor = sknBaseInfoResponse.getProductFeatureFactor(); 53 this.factor = sknBaseInfoResponse.getProductFeatureFactor();
54 } 54 }
55 55
56 - public void setStrategys(List<StrategyEnum> strategys) {  
57 - this.strategys = strategys; 56 + public void setStrategy(StrategyEnum strategy) {
  57 + this.strategy = strategy;
58 } 58 }
59 59
60 public void setScore(Double score) { 60 public void setScore(Double score) {
@@ -82,11 +82,10 @@ public class RecallMergerResult { @@ -82,11 +82,10 @@ public class RecallMergerResult {
82 return priceArea; 82 return priceArea;
83 } 83 }
84 84
85 - public List<StrategyEnum> getStrategys() {  
86 - return strategys; 85 + public StrategyEnum getStrategy() {
  86 + return strategy;
87 } 87 }
88 88
89 -  
90 public Double getScore() { 89 public Double getScore() {
91 return score; 90 return score;
92 } 91 }
@@ -29,4 +29,11 @@ public class PageProductIdBitSet implements Serializable{ @@ -29,4 +29,11 @@ public class PageProductIdBitSet implements Serializable{
29 return productIdBitSet.cardinality(); 29 return productIdBitSet.cardinality();
30 } 30 }
31 31
  32 + public BitSet getProductIdBitSet() {
  33 + return productIdBitSet;
  34 + }
  35 +
  36 + public void setProductIdBitSet(BitSet productIdBitSet) {
  37 + this.productIdBitSet = productIdBitSet;
  38 + }
32 } 39 }
@@ -18,17 +18,12 @@ import java.util.Arrays; @@ -18,17 +18,12 @@ import java.util.Arrays;
18 /** 18 /**
19 * 召回请求 19 * 召回请求
20 */ 20 */
21 -public class RecallRequest implements ICacheRequest,IRecallRequest { 21 +public class RecallRequest implements ICacheRequest, IRecallRequest {
22 22
23 private ParamQueryFilter paramQueryFilter; 23 private ParamQueryFilter paramQueryFilter;
24 private IStrategy strategy; 24 private IStrategy strategy;
25 private RedisKeyBuilder redisKeyBuilder; 25 private RedisKeyBuilder redisKeyBuilder;
26 26
27 - public RecallRequest(IStrategy strategy) {  
28 - this.strategy = strategy;  
29 - this.redisKeyBuilder = genRedisKeyBuilder();  
30 - }  
31 -  
32 public RecallRequest(ParamQueryFilter paramQueryFilter, IStrategy strategy) { 27 public RecallRequest(ParamQueryFilter paramQueryFilter, IStrategy strategy) {
33 this.paramQueryFilter = paramQueryFilter; 28 this.paramQueryFilter = paramQueryFilter;
34 this.strategy = strategy; 29 this.strategy = strategy;
@@ -59,6 +54,10 @@ public class RecallRequest implements ICacheRequest,IRecallRequest { @@ -59,6 +54,10 @@ public class RecallRequest implements ICacheRequest,IRecallRequest {
59 } 54 }
60 55
61 @Override 56 @Override
  57 + public IStrategy strategy() {
  58 + return strategy;
  59 + }
  60 +
62 public StrategyEnum requestStrategy() { 61 public StrategyEnum requestStrategy() {
63 return this.strategy.strategtEnum(); 62 return this.strategy.strategtEnum();
64 } 63 }
@@ -66,7 +65,7 @@ public class RecallRequest implements ICacheRequest,IRecallRequest { @@ -66,7 +65,7 @@ public class RecallRequest implements ICacheRequest,IRecallRequest {
66 @Override 65 @Override
67 public SearchParam searchParam() { 66 public SearchParam searchParam() {
68 SearchParam searchParam = new SearchParam(); 67 SearchParam searchParam = new SearchParam();
69 - if(paramQueryFilter!=null && paramQueryFilter.getParamQuery()!=null){ 68 + if (paramQueryFilter != null && paramQueryFilter.getParamQuery() != null) {
70 searchParam.setQuery(this.paramQueryFilter.getParamQuery()); 69 searchParam.setQuery(this.paramQueryFilter.getParamQuery());
71 } 70 }
72 searchParam.setFiter(this.getRealFilter()); 71 searchParam.setFiter(this.getRealFilter());
@@ -79,16 +78,17 @@ public class RecallRequest implements ICacheRequest,IRecallRequest { @@ -79,16 +78,17 @@ public class RecallRequest implements ICacheRequest,IRecallRequest {
79 78
80 private QueryBuilder getRealFilter() { 79 private QueryBuilder getRealFilter() {
81 BoolQueryBuilder realFilter = QueryBuilders.boolQuery(); 80 BoolQueryBuilder realFilter = QueryBuilders.boolQuery();
82 - if(strategy!=null && strategy.extendFilter() != null){ 81 + if (strategy != null && strategy.extendFilter() != null) {
83 realFilter.must(this.strategy.extendFilter()); 82 realFilter.must(this.strategy.extendFilter());
84 } 83 }
85 - if(paramQueryFilter!=null && paramQueryFilter.getParamFilter() != null){ 84 + if (paramQueryFilter != null && paramQueryFilter.getParamFilter() != null) {
86 realFilter.must(this.paramQueryFilter.getParamFilter()); 85 realFilter.must(this.paramQueryFilter.getParamFilter());
87 } 86 }
88 - if(realFilter.hasClauses()){ 87 + if (realFilter.hasClauses()) {
89 return realFilter; 88 return realFilter;
90 } 89 }
91 return null; 90 return null;
92 } 91 }
93 92
  93 +
94 } 94 }