Authored by hugufei

Merge branch 'master' into hongren

Showing 17 changed files with 328 additions and 106 deletions
1 package com.yoho.search.recall.scene.beans.builder; 1 package com.yoho.search.recall.scene.beans.builder;
2 2
3 -import com.alibaba.fastjson.JSON;  
4 import com.yoho.search.recall.scene.beans.strategy.StrategyEnum; 3 import com.yoho.search.recall.scene.beans.strategy.StrategyEnum;
5 import com.yoho.search.recall.scene.models.common.RecallMergerResult; 4 import com.yoho.search.recall.scene.models.common.RecallMergerResult;
6 import com.yoho.search.recall.scene.models.req.RecallRequest; 5 import com.yoho.search.recall.scene.models.req.RecallRequest;
@@ -178,7 +178,7 @@ public class UserRecallResponseBuilder { @@ -178,7 +178,7 @@ public class UserRecallResponseBuilder {
178 continue; 178 continue;
179 } 179 }
180 //2)如果是推荐出来的,则单独加分[以减分的方式依次保证顺序] 180 //2)如果是推荐出来的,则单独加分[以减分的方式依次保证顺序]
181 - if (strategy.equals(StrategyEnum.REC_SKN)) { 181 + if (strategy.equals(StrategyEnum.REC_SKN)||strategy.equals(StrategyEnum.RT_SIM_SKN)) {
182 sknResult.setScore((double) recommendSknIndex--); 182 sknResult.setScore((double) recommendSknIndex--);
183 continue; 183 continue;
184 } 184 }
@@ -246,19 +246,22 @@ public class UserRecallResponseBuilder { @@ -246,19 +246,22 @@ public class UserRecallResponseBuilder {
246 } 246 }
247 } 247 }
248 248
249 - // 2、加入全部【除直通车和直接推荐】外的商品 249 + // 2、加入全部【除直通车和推荐】外的商品
250 iterator = sknResultList.iterator(); 250 iterator = sknResultList.iterator();
251 while (iterator.hasNext()) { 251 while (iterator.hasNext()) {
252 RecallMergerResult.SknResult sknResult = iterator.next(); 252 RecallMergerResult.SknResult sknResult = iterator.next();
253 - if (!Arrays.asList(StrategyEnum.DIRECT_TRAIN,StrategyEnum.REC_SKN).contains(sknResult.getStrategy())){ 253 + if (!Arrays.asList(StrategyEnum.DIRECT_TRAIN,StrategyEnum.REC_SKN,StrategyEnum.RT_SIM_SKN).contains(sknResult.getStrategy())){
254 results.add(sknResult); 254 results.add(sknResult);
255 iterator.remove(); 255 iterator.remove();
256 } 256 }
257 } 257 }
258 258
259 - // 3、插入【直接推荐】的商品-随机插入 259 + // 3、插入【REC_SKN】的商品-随机插入
260 this.addByIndexIndex(sknResultList, results, 1, 2, (sknResult -> StrategyEnum.REC_SKN.equals(sknResult.getStrategy())),dropTransfer); 260 this.addByIndexIndex(sknResultList, results, 1, 2, (sknResult -> StrategyEnum.REC_SKN.equals(sknResult.getStrategy())),dropTransfer);
261 261
  262 + // 4、插入【RT_SIM_SKN】的商品-随机插入
  263 + this.addByIndexIndex(sknResultList, results, 2, 3, (sknResult -> StrategyEnum.RT_SIM_SKN.equals(sknResult.getStrategy())),dropTransfer);
  264 +
262 // 4、插入【直通车】商品-随机插入 265 // 4、插入【直通车】商品-随机插入
263 int directTrainIndexInterval = searchDynamicConfigService.directTrainIndexInterval(); 266 int directTrainIndexInterval = searchDynamicConfigService.directTrainIndexInterval();
264 this.addByIndexIndex(sknResultList, results, 4, directTrainIndexInterval, (sknResult -> StrategyEnum.DIRECT_TRAIN.equals(sknResult.getStrategy())),dropTransfer); 267 this.addByIndexIndex(sknResultList, results, 4, directTrainIndexInterval, (sknResult -> StrategyEnum.DIRECT_TRAIN.equals(sknResult.getStrategy())),dropTransfer);
@@ -269,12 +272,7 @@ public class UserRecallResponseBuilder { @@ -269,12 +272,7 @@ public class UserRecallResponseBuilder {
269 /** 272 /**
270 * 单策略召回时,超出数量直接丢弃 273 * 单策略召回时,超出数量直接丢弃
271 */ 274 */
272 - private static Transfer<RecallMergerResult.SknResult,Boolean> dropTransfer = new Transfer<RecallMergerResult.SknResult, Boolean>() {  
273 - @Override  
274 - public Boolean transfer(RecallMergerResult.SknResult sknResult) {  
275 - return sknResult.isOnlyOneStrategy()?true:false;  
276 - }  
277 - }; 275 + private static Transfer<RecallMergerResult.SknResult,Boolean> dropTransfer = (sknResult) ->sknResult.isOnlyOneStrategy()?true:false;
278 276
279 private static <T> void addByIndexIndex(List<T> fromList, List<T> toList,int fromIndex, int indexInterval,Transfer<T, Boolean> match,Transfer<T, Boolean> drop) { 277 private static <T> void addByIndexIndex(List<T> fromList, List<T> toList,int fromIndex, int indexInterval,Transfer<T, Boolean> match,Transfer<T, Boolean> drop) {
280 Iterator<T> iterator = fromList.iterator(); 278 Iterator<T> iterator = fromList.iterator();
@@ -307,15 +305,18 @@ public class UserRecallResponseBuilder { @@ -307,15 +305,18 @@ public class UserRecallResponseBuilder {
307 305
308 public static void main(String[] args) { 306 public static void main(String[] args) {
309 List<Integer> fromList = new ArrayList<>(); 307 List<Integer> fromList = new ArrayList<>();
310 - for (int index =1;index <=20;index ++){ 308 + for (int index =1;index <=30;index ++){
311 fromList.add(index); 309 fromList.add(index);
312 } 310 }
313 311
314 List<Integer> toList = new ArrayList<>(); 312 List<Integer> toList = new ArrayList<>();
315 - for (int index =0;index <1;index ++){ 313 + for (int index =0;index <100;index ++){
316 toList.add(0); 314 toList.add(0);
317 } 315 }
318 addByIndexIndex(fromList, toList, 1, 2, (value -> value%2==1),null); 316 addByIndexIndex(fromList, toList, 1, 2, (value -> value%2==1),null);
  317 +
  318 + addByIndexIndex(fromList, toList, 2, 3, (value -> value%2==0),null);
  319 +
319 System.out.println(toList); 320 System.out.println(toList);
320 // addByIndexIndex(fromList, toList, 4, 4, (value -> value%2==0)); 321 // addByIndexIndex(fromList, toList, 4, 4, (value -> value%2==0));
321 // System.out.println(toList); 322 // System.out.println(toList);
1 package com.yoho.search.recall.scene.beans.cache; 1 package com.yoho.search.recall.scene.beans.cache;
2 2
3 import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder; 3 import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
  4 +import com.yoho.search.base.utils.CollectionUtils;
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;
6 import com.yoho.search.common.cache.impls.EhCache; 7 import com.yoho.search.common.cache.impls.EhCache;
@@ -9,9 +10,13 @@ import com.yoho.search.common.cache.model.CacheObject; @@ -9,9 +10,13 @@ import com.yoho.search.common.cache.model.CacheObject;
9 import com.yoho.search.core.es.model.SearchParam; 10 import com.yoho.search.core.es.model.SearchParam;
10 import com.yoho.search.core.es.model.SearchResult; 11 import com.yoho.search.core.es.model.SearchResult;
11 import com.yoho.search.recall.scene.beans.persional.PageProductIdBitSetComponent; 12 import com.yoho.search.recall.scene.beans.persional.PageProductIdBitSetComponent;
  13 +import com.yoho.search.recall.scene.beans.strategy.IStrategy;
  14 +import com.yoho.search.recall.scene.beans.strategy.impls.IRecallSknStrategy;
  15 +import com.yoho.search.recall.scene.beans.strategy.impls.RealTimeSimilarSknStrategy;
12 import com.yoho.search.recall.scene.beans.strategy.impls.RecommendSknStrategy; 16 import com.yoho.search.recall.scene.beans.strategy.impls.RecommendSknStrategy;
13 import com.yoho.search.recall.scene.models.common.ParamQueryFilter; 17 import com.yoho.search.recall.scene.models.common.ParamQueryFilter;
14 import com.yoho.search.recall.scene.models.personal.PageProductIdBitSet; 18 import com.yoho.search.recall.scene.models.personal.PageProductIdBitSet;
  19 +import com.yoho.search.recall.scene.models.personal.UserPersonalFactor;
15 import com.yoho.search.recall.scene.models.req.RecallRequest; 20 import com.yoho.search.recall.scene.models.req.RecallRequest;
16 import com.yoho.search.recall.scene.models.req.RecallRequestResponse; 21 import com.yoho.search.recall.scene.models.req.RecallRequestResponse;
17 import com.yoho.search.recall.scene.models.req.RecallResponse; 22 import com.yoho.search.recall.scene.models.req.RecallResponse;
@@ -50,25 +55,63 @@ public class SknRecallCacheBean { @@ -50,25 +55,63 @@ public class SknRecallCacheBean {
50 * 55 *
51 * @return 56 * @return
52 */ 57 */
53 - public List<RecallRequestResponse> batchRecallRecommedSknList(UserRecallRequest userRecallRequest, List<Integer> recommedSknList, int maxReturnCount) { 58 + public List<RecallRequestResponse> batchRecallBySknList(UserRecallRequest userRecallRequest, UserPersonalFactor userPersonalFactor, int maxReturnCount) {
54 try { 59 try {
55 - if (recommedSknList == null || recommedSknList.isEmpty()) {  
56 - return new ArrayList<>(); 60 + //1、获取SKN,以及每个skn对应的找回类型
  61 + List<Integer> filterSknList = new ArrayList<>();
  62 + if (userPersonalFactor.getRecommendSknList() != null) {
  63 + filterSknList.addAll(userPersonalFactor.getRecommendSknList());
57 } 64 }
58 - List<Integer> filterSknList; 65 + if (userPersonalFactor.getRealTimeSimilarSknList() != null) {
  66 + filterSknList.addAll(userPersonalFactor.getRealTimeSimilarSknList());
  67 + }
  68 + //2、执行查询
  69 + List<Integer> filterSknResults;
59 if (recallWithCache) { 70 if (recallWithCache) {
60 - filterSknList = this.filterRecommendWithCache(userRecallRequest, recommedSknList); 71 + filterSknResults = this.filterRecommendWithCache(userRecallRequest, filterSknList);
61 } else { 72 } else {
62 - filterSknList = this.filterRecommedSknListByEs(userRecallRequest, recommedSknList); 73 + filterSknResults = this.filterRecommedSknListByEs(userRecallRequest, filterSknList);
63 } 74 }
64 - RECALL_NEW_LOGGER.info("recommedSknList size is [{}], filterSknListSize is[{}]", recommedSknList.size(), filterSknList.size());  
65 - return this.buildResults(userRecallRequest, filterSknList, maxReturnCount); 75 + //3、构造结果
  76 + List<RecallRequestResponse> results = new ArrayList<>();
  77 + ParamQueryFilter paramQueryFilter = userRecallRequest.getParamQueryFilter();
  78 + results.addAll(this.buildResults(paramQueryFilter, userPersonalFactor.getRecommendSknList(), RecommendSknStrategy.class, filterSknResults, maxReturnCount));
  79 + results.addAll(this.buildResults(paramQueryFilter, userPersonalFactor.getRealTimeSimilarSknList(), RealTimeSimilarSknStrategy.class, filterSknResults, maxReturnCount));
  80 + return results;
66 } catch (Exception e) { 81 } catch (Exception e) {
67 RECALL_NEW_LOGGER.error(e.getMessage(), e); 82 RECALL_NEW_LOGGER.error(e.getMessage(), e);
68 return new ArrayList<>(); 83 return new ArrayList<>();
69 } 84 }
70 } 85 }
71 86
  87 + private List<RecallRequestResponse> buildResults(ParamQueryFilter paramQueryFilter, List<Integer> filterSkns, Class<? extends IRecallSknStrategy> clazz, List<Integer> sknResults, int maxReturnCount) {
  88 + if (filterSkns == null || filterSkns.isEmpty() || sknResults == null || sknResults.isEmpty()) {
  89 + return new ArrayList<>();
  90 + }
  91 + List<RecallRequestResponse> results = new ArrayList<>();
  92 + for (Integer skn : filterSkns) {
  93 + if (results.size() >= maxReturnCount) {
  94 + break;
  95 + }
  96 + if(!sknResults.contains(skn)){
  97 + continue;
  98 + }
  99 + RecallRequest recallRequest = new RecallRequest(paramQueryFilter, this.getRecallSknStrategy(clazz, skn));
  100 + RecallRequestResponse recallRequestResponse = new RecallRequestResponse(recallRequest);
  101 + recallRequestResponse.setResponse(new RecallResponse(1L, Arrays.asList(skn)), false);
  102 + results.add(recallRequestResponse);
  103 + }
  104 + return results;
  105 + }
  106 +
  107 + private IRecallSknStrategy getRecallSknStrategy(Class<? extends IRecallSknStrategy> clazz, Integer skn) {
  108 + if (clazz.isAssignableFrom(RecommendSknStrategy.class)) {
  109 + return new RecommendSknStrategy(skn);
  110 + } else {
  111 + return new RealTimeSimilarSknStrategy(skn);
  112 + }
  113 + }
  114 +
72 /** 115 /**
73 * 从ehcahc或者redis中构造返回结果 116 * 从ehcahc或者redis中构造返回结果
74 * 117 *
@@ -198,27 +241,4 @@ public class SknRecallCacheBean { @@ -198,27 +241,4 @@ public class SknRecallCacheBean {
198 return results; 241 return results;
199 } 242 }
200 243
201 - /**  
202 - * 将推荐的skn构造成召回对象  
203 - *  
204 - * @return  
205 - */  
206 - private List<RecallRequestResponse> buildResults(UserRecallRequest userRecallRequest, final List<Integer> recommedSknList, int maxReturnCount) {  
207 - List<RecallRequestResponse> results = new ArrayList<>();  
208 - if (recommedSknList == null || recommedSknList.isEmpty()) {  
209 - return results;  
210 - }  
211 - ParamQueryFilter paramQueryFilter = userRecallRequest.getParamQueryFilter();  
212 - for (Integer recommendSkn : recommedSknList) {  
213 - if (results.size() >= maxReturnCount) {  
214 - break;  
215 - }  
216 - RecallRequest recallRequest = new RecallRequest(paramQueryFilter, new RecommendSknStrategy(recommendSkn));  
217 - RecallRequestResponse recallRequestResponse = new RecallRequestResponse(recallRequest);  
218 - recallRequestResponse.setResponse(new RecallResponse(1L, Arrays.asList(recommendSkn)), false);  
219 - results.add(recallRequestResponse);  
220 - }  
221 - return results;  
222 - }  
223 -  
224 } 244 }
@@ -104,7 +104,7 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us @@ -104,7 +104,7 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us
104 long begin = System.currentTimeMillis(); 104 long begin = System.currentTimeMillis();
105 105
106 //1、处理实时推荐SKN的召回 106 //1、处理实时推荐SKN的召回
107 - CompletableFuture<List<RecallRequestResponse>> recommendSknCompletableFuture = this.doRecallRecommendSkn(userRecallRequest, userPersonalFactor); 107 + CompletableFuture<List<RecallRequestResponse>> recallBySknListCompletableFuture = this.doRecallBySknList(userRecallRequest, userPersonalFactor);
108 108
109 //2、处理通用召回 109 //2、处理通用召回
110 CompletableFuture<List<RecallRequestResponse>> commonCompletableFuture = this.doRecallCommon(userRecallRequest, userPersonalFactor); 110 CompletableFuture<List<RecallRequestResponse>> commonCompletableFuture = this.doRecallCommon(userRecallRequest, userPersonalFactor);
@@ -118,7 +118,7 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us @@ -118,7 +118,7 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us
118 //5、构造最终返回结果投入额 118 //5、构造最终返回结果投入额
119 List<RecallRequestResponse> batchRequestResults = new ArrayList<>(); 119 List<RecallRequestResponse> batchRequestResults = new ArrayList<>();
120 120
121 - batchRequestResults.addAll(this.getResultFromCompletableFuture(recommendSknCompletableFuture));//推荐的skn放在第一个,不然merger的时候可能会无序 121 + batchRequestResults.addAll(this.getResultFromCompletableFuture(recallBySknListCompletableFuture));//按skn召回放在第一个,不然merger的时候可能会无序
122 batchRequestResults.addAll(this.getResultFromCompletableFuture(commonCompletableFuture)); 122 batchRequestResults.addAll(this.getResultFromCompletableFuture(commonCompletableFuture));
123 batchRequestResults.addAll(this.getResultFromCompletableFuture(realTimeSortBrandCompletableFuture)); 123 batchRequestResults.addAll(this.getResultFromCompletableFuture(realTimeSortBrandCompletableFuture));
124 batchRequestResults.addAll(this.getResultFromCompletableFuture(forecastSortBrandCompletableFuture)); 124 batchRequestResults.addAll(this.getResultFromCompletableFuture(forecastSortBrandCompletableFuture));
@@ -169,12 +169,13 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us @@ -169,12 +169,13 @@ public class UserRecallCacheBean extends AbstractCacheBean<UserRecallRequest, Us
169 * @param userPersonalFactor 169 * @param userPersonalFactor
170 * @return 170 * @return
171 */ 171 */
172 - private CompletableFuture<List<RecallRequestResponse>> doRecallRecommendSkn(UserRecallRequest userRecallRequest, UserPersonalFactor userPersonalFactor) { 172 + private CompletableFuture<List<RecallRequestResponse>> doRecallBySknList(UserRecallRequest userRecallRequest, UserPersonalFactor userPersonalFactor) {
173 return CompletableFuture.supplyAsync(() -> { 173 return CompletableFuture.supplyAsync(() -> {
174 long begin = System.currentTimeMillis(); 174 long begin = System.currentTimeMillis();
175 - int requestCount = userPersonalFactor.getRecommendSknList() == null ? 0 : userPersonalFactor.getRecommendSknList().size();  
176 - List<RecallRequestResponse> recommendSknRequestResponses = sknRecallCacheBean.batchRecallRecommedSknList(userRecallRequest, userPersonalFactor.getRecommendSknList(), 8);  
177 - RECALL_NEW_LOGGER.info("UserRecallCacheBean[2]-doRecallRecommendSkn,requestCount is [{}], cost is [{}]", requestCount, System.currentTimeMillis() - begin); 175 + int recommendSknCount = userPersonalFactor.getRecommendSknList() == null ? 0 : userPersonalFactor.getRecommendSknList().size();
  176 + int realTimeSimilarSknCount = userPersonalFactor.getRealTimeSimilarSknList() == null ? 0 : userPersonalFactor.getRealTimeSimilarSknList().size();
  177 + List<RecallRequestResponse> recommendSknRequestResponses = sknRecallCacheBean.batchRecallBySknList(userRecallRequest,userPersonalFactor, 8);
  178 + RECALL_NEW_LOGGER.info("UserRecallCacheBean[2]-doRecallRecommendSkn,recommendSknCount is [{}],realTimeSimilarSknCount is[{}] ,cost is [{}]", recommendSknCount, realTimeSimilarSknCount,System.currentTimeMillis() - begin);
178 return recommendSknRequestResponses; 179 return recommendSknRequestResponses;
179 }, recallExecutorService); 180 }, recallExecutorService);
180 } 181 }
@@ -98,8 +98,9 @@ public class QueryUserPersionalFactorBean { @@ -98,8 +98,9 @@ public class QueryUserPersionalFactorBean {
98 List<SortPriceAreas> sortPriceAreasList = this.getSortPriceAreasListWithSort(userFactor, pageFactor); 98 List<SortPriceAreas> sortPriceAreasList = this.getSortPriceAreasListWithSort(userFactor, pageFactor);
99 //5、构造推荐的skn列表 99 //5、构造推荐的skn列表
100 List<Integer> recommendSknList = userFactor.getRecommendSknList(); 100 List<Integer> recommendSknList = userFactor.getRecommendSknList();
  101 + List<Integer> realTimeSimilarSknList = userFactor.getRealTimeSimilarSknList();
101 //6、返回最终结果 102 //6、返回最终结果
102 - return new UserPersonalFactor(realTimeSortBrandList, forecastSortBrandList, sortPriceAreasList, recommendSknList, userFactor.getVector()); 103 + return new UserPersonalFactor(realTimeSortBrandList, forecastSortBrandList, sortPriceAreasList, recommendSknList,realTimeSimilarSknList, userFactor.getVector());
103 } 104 }
104 105
105 private Map<Integer, List<Integer>> getPageBrand2MiSortIdsMap(PagePersonalFactor pageFactor) { 106 private Map<Integer, List<Integer>> getPageBrand2MiSortIdsMap(PagePersonalFactor pageFactor) {
@@ -6,6 +6,7 @@ public enum StrategyEnum { @@ -6,6 +6,7 @@ public enum StrategyEnum {
6 DIRECT_TRAIN(109),//直通车 6 DIRECT_TRAIN(109),//直通车
7 7
8 REC_SKN(99),//实时推荐的商品 8 REC_SKN(99),//实时推荐的商品
  9 + RT_SIM_SKN(98),//实时推荐的相似商品
9 10
10 REC_S_B_HEAT_VALUE(41),//实时的品牌+品类的人气值 11 REC_S_B_HEAT_VALUE(41),//实时的品牌+品类的人气值
11 REC_S_B_REDUCE_PRICE(42),//实时的品牌+品类的最新降价 12 REC_S_B_REDUCE_PRICE(42),//实时的品牌+品类的最新降价
  1 +package com.yoho.search.recall.scene.beans.strategy.impls;
  2 +
  3 +import com.yoho.search.recall.scene.beans.helper.ExtendFilterHelper;
  4 +import com.yoho.search.recall.scene.beans.helper.SortBuilderHelper;
  5 +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.constants.CacheTimeConstants;
  8 +import org.elasticsearch.index.query.QueryBuilder;
  9 +import org.elasticsearch.search.sort.SortBuilder;
  10 +
  11 +public abstract class IRecallSknStrategy implements IStrategy {
  12 +
  13 + private Integer skn;
  14 +
  15 + public IRecallSknStrategy(Integer skn) {
  16 + this.skn = skn;
  17 + }
  18 +
  19 + public abstract StrategyEnum strategtEnum();
  20 +
  21 + @Override
  22 + public QueryBuilder extendFilter() {
  23 + return ExtendFilterHelper.productSknFilter(this.skn);
  24 + }
  25 +
  26 + @Override
  27 + public SortBuilder<?> sortBuilder() {
  28 + return SortBuilderHelper.getIdDescSort();
  29 + }
  30 +
  31 + @Override
  32 + public int size() {
  33 + return 1;
  34 + }
  35 +
  36 + @Override
  37 + public int cacheTimeInMinute() {
  38 + return CacheTimeConstants.SKN_RECALL_CACHE_TIME;
  39 + }
  40 +
  41 + @Override
  42 + public String strategyCacheKey() {
  43 + StringBuilder sb = defaultStrategyKey();
  44 + sb.append(this.skn==null?"0": skn.toString());
  45 + return sb.toString();
  46 + }
  47 +
  48 +}
  1 +package com.yoho.search.recall.scene.beans.strategy.impls;
  2 +
  3 +import com.yoho.search.recall.scene.beans.strategy.StrategyEnum;
  4 +
  5 +/**
  6 + * 推荐skn的召回策略
  7 + *
  8 + * @author gufei.hu
  9 + *
  10 + */
  11 +public class RealTimeSimilarSknStrategy extends IRecallSknStrategy{
  12 +
  13 + public RealTimeSimilarSknStrategy(Integer recommendSkn) {
  14 + super(recommendSkn);
  15 + }
  16 +
  17 + @Override
  18 + public StrategyEnum strategtEnum() {
  19 + return StrategyEnum.RT_SIM_SKN;
  20 + }
  21 +
  22 +}
@@ -14,12 +14,10 @@ import org.elasticsearch.search.sort.SortBuilder; @@ -14,12 +14,10 @@ import org.elasticsearch.search.sort.SortBuilder;
14 * @author gufei.hu 14 * @author gufei.hu
15 * 15 *
16 */ 16 */
17 -public class RecommendSknStrategy implements IStrategy {  
18 -  
19 - private Integer recommendSkn; 17 +public class RecommendSknStrategy extends IRecallSknStrategy{
20 18
21 public RecommendSknStrategy(Integer recommendSkn) { 19 public RecommendSknStrategy(Integer recommendSkn) {
22 - this.recommendSkn = recommendSkn; 20 + super(recommendSkn);
23 } 21 }
24 22
25 @Override 23 @Override
@@ -27,30 +25,4 @@ public class RecommendSknStrategy implements IStrategy { @@ -27,30 +25,4 @@ public class RecommendSknStrategy implements IStrategy {
27 return StrategyEnum.REC_SKN; 25 return StrategyEnum.REC_SKN;
28 } 26 }
29 27
30 - @Override  
31 - public QueryBuilder extendFilter() {  
32 - return ExtendFilterHelper.productSknFilter(this.recommendSkn);  
33 - }  
34 -  
35 - @Override  
36 - public SortBuilder<?> sortBuilder() {  
37 - return SortBuilderHelper.getIdDescSort();  
38 - }  
39 -  
40 - @Override  
41 - public int size() {  
42 - return 1;  
43 - }  
44 -  
45 - @Override  
46 - public int cacheTimeInMinute() {  
47 - return CacheTimeConstants.RECOMMEND_SKN_CACHE_TIME;  
48 - }  
49 -  
50 - @Override  
51 - public String strategyCacheKey() {  
52 - StringBuilder sb = defaultStrategyKey();  
53 - sb.append(this.recommendSkn==null?"0": recommendSkn.toString());  
54 - return sb.toString();  
55 - }  
56 } 28 }
@@ -10,7 +10,7 @@ public class CacheTimeConstants { @@ -10,7 +10,7 @@ public class CacheTimeConstants {
10 public static final int COMMON_RECALL_STRATEGY_CACHE_TIME = 10 ; 10 public static final int COMMON_RECALL_STRATEGY_CACHE_TIME = 10 ;
11 11
12 //SKN的的缓存 - 60分钟 12 //SKN的的缓存 - 60分钟
13 - public static final int RECOMMEND_SKN_CACHE_TIME = 60 ; 13 + public static final int SKN_RECALL_CACHE_TIME = 60 ;
14 14
15 //品类+品牌的缓存 - 60分钟 15 //品类+品牌的缓存 - 60分钟
16 public static final int SORT_BRAND_RECALL_STRATEGY_CACHE_TIME = 60 ; 16 public static final int SORT_BRAND_RECALL_STRATEGY_CACHE_TIME = 60 ;
@@ -12,6 +12,7 @@ public class UserPersonalFactor { @@ -12,6 +12,7 @@ public class UserPersonalFactor {
12 private List<SortBrand> forecastSortBrandList; 12 private List<SortBrand> forecastSortBrandList;
13 private List<SortPriceAreas> sortPriceAreasList; 13 private List<SortPriceAreas> sortPriceAreasList;
14 private List<Integer> recommendSknList; 14 private List<Integer> recommendSknList;
  15 + private List<Integer> realTimeSimilarSknList;
15 private String vector; 16 private String vector;
16 17
17 public UserPersonalFactor (){ 18 public UserPersonalFactor (){
@@ -19,14 +20,16 @@ public class UserPersonalFactor { @@ -19,14 +20,16 @@ public class UserPersonalFactor {
19 this.forecastSortBrandList = new ArrayList<>(); 20 this.forecastSortBrandList = new ArrayList<>();
20 this.sortPriceAreasList = new ArrayList<>(); 21 this.sortPriceAreasList = new ArrayList<>();
21 this.recommendSknList = new ArrayList<>(); 22 this.recommendSknList = new ArrayList<>();
  23 + this.realTimeSimilarSknList = realTimeSimilarSknList;
22 this.vector = ""; 24 this.vector = "";
23 } 25 }
24 26
25 - public UserPersonalFactor(List<SortBrand> realTimeSortBrandList,List<SortBrand> forecastSortBrandList,List<SortPriceAreas> sortPriceAreasList,List<Integer> recommendSknList, String vector) { 27 + public UserPersonalFactor(List<SortBrand> realTimeSortBrandList,List<SortBrand> forecastSortBrandList,List<SortPriceAreas> sortPriceAreasList,List<Integer> recommendSknList,List<Integer> realTimeSimilarSknList, String vector) {
26 this.realTimeSortBrandList = realTimeSortBrandList; 28 this.realTimeSortBrandList = realTimeSortBrandList;
27 this.forecastSortBrandList = forecastSortBrandList; 29 this.forecastSortBrandList = forecastSortBrandList;
28 this.sortPriceAreasList = sortPriceAreasList; 30 this.sortPriceAreasList = sortPriceAreasList;
29 this.recommendSknList = recommendSknList; 31 this.recommendSknList = recommendSknList;
  32 + this.realTimeSimilarSknList = realTimeSimilarSknList;
30 this.vector = vector; 33 this.vector = vector;
31 } 34 }
32 35
@@ -62,5 +65,7 @@ public class UserPersonalFactor { @@ -62,5 +65,7 @@ public class UserPersonalFactor {
62 return sortPriceAreasList==null?0:sortPriceAreasList.size(); 65 return sortPriceAreasList==null?0:sortPriceAreasList.size();
63 } 66 }
64 67
65 - 68 + public List<Integer> getRealTimeSimilarSknList() {
  69 + return realTimeSimilarSknList;
  70 + }
66 } 71 }
  1 +package com.yoho.search.restapi.miniapp;
  2 +
  3 +import com.yoho.search.common.downgrade.persional.PersionalRateLimit;
  4 +import com.yoho.search.common.utils.HttpServletRequestUtils;
  5 +import com.yoho.search.models.SearchApiResult;
  6 +import com.yoho.search.service.scene.miniapp.MiniappFuzzySceneService;
  7 +import org.springframework.beans.factory.annotation.Autowired;
  8 +import org.springframework.stereotype.Controller;
  9 +import org.springframework.web.bind.annotation.RequestMapping;
  10 +import org.springframework.web.bind.annotation.RequestMethod;
  11 +import org.springframework.web.bind.annotation.ResponseBody;
  12 +
  13 +import javax.servlet.http.HttpServletRequest;
  14 +import java.util.Map;
  15 +
  16 +@Controller
  17 +public class MiniappProductListController {
  18 +
  19 + @Autowired
  20 + private MiniappFuzzySceneService miniappFuzzySceneService;
  21 +
  22 + /**
  23 + * 小程序模糊搜索列表
  24 + *
  25 + * @return
  26 + */
  27 + @PersionalRateLimit(isOrderUseable = true)
  28 + @RequestMapping(method = RequestMethod.GET, value = "/miniapp/fuzzy/productList")
  29 + @ResponseBody
  30 + public SearchApiResult miniappFuzzyProductList(HttpServletRequest request) {
  31 + Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
  32 + SearchApiResult searchApiResult = miniappFuzzySceneService.productList(paramMap);
  33 + return searchApiResult;
  34 + }
  35 +
  36 + /**
  37 + * 小程序模糊搜索筛选项
  38 + *
  39 + * @return
  40 + */
  41 + @PersionalRateLimit(isOrderUseable = false)
  42 + @RequestMapping(method = RequestMethod.GET, value = "/miniapp/fuzzy/aggregations")
  43 + @ResponseBody
  44 + public SearchApiResult miniappFuzzyAggregations(HttpServletRequest request) {
  45 + Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
  46 + return miniappFuzzySceneService.aggregations(paramMap);
  47 + }
  48 +
  49 +}
@@ -35,13 +35,7 @@ public class CouponSceneService extends AbstractSceneService { @@ -35,13 +35,7 @@ public class CouponSceneService extends AbstractSceneService {
35 @Override 35 @Override
36 public void addParamsToParamMap(Map<String, String> paramMap) { 36 public void addParamsToParamMap(Map<String, String> paramMap) {
37 super.addDefaultParamsToParamMap(paramMap); 37 super.addDefaultParamsToParamMap(paramMap);
38 - paramMap.put(SearchRequestParams.PARAM_SEARCH_ISLIMITED, "N");// 不支持限定  
39 - paramMap.put(SearchRequestParams.PARAM_SEARCH_CONTAIN_SECKILL, "N");// 不支持秒杀  
40 - paramMap.put(SearchRequestParams.PARAM_SEARCH_ISADVANCE, "N");// 不支持预售  
41 - paramMap.put(SearchRequestParams.PARAM_SEARCH_BUNDLETYPE, "0");// 不支持套餐  
42 - paramMap.put(SearchRequestParams.PARAM_SEARCH_ISLIMITEDBUY, "N");// 不支持限购  
43 - paramMap.put(SearchRequestParams.PARAM_SEARCH_ISDESPOSITADVANCE, "N");// 不支持定金预售  
44 - paramMap.put(SearchRequestParams.PARAM_SEARCH_ISLIMITTIMEADVANCE, "N");// 不支持定金促销 38 + super.filterNotNormalToMap(paramMap);
45 } 39 }
46 40
47 @Override 41 @Override
@@ -135,7 +135,7 @@ public class FuzzySceneService extends AbstractSceneService { @@ -135,7 +135,7 @@ public class FuzzySceneService extends AbstractSceneService {
135 * @param paramMap 135 * @param paramMap
136 * @return 136 * @return
137 */ 137 */
138 - private void addSuggestion(SearchApiResult searchResult, Map<String, String> paramMap) { 138 + public void addSuggestion(SearchApiResult searchResult, Map<String, String> paramMap) {
139 if (searchResult == null || searchResult.getCode() != 200 || searchResult.getData() == null) { 139 if (searchResult == null || searchResult.getCode() != 200 || searchResult.getData() == null) {
140 return; 140 return;
141 } 141 }
@@ -186,13 +186,4 @@ public class WebProductListService extends AbstractCacheAbleService { @@ -186,13 +186,4 @@ public class WebProductListService extends AbstractCacheAbleService {
186 return searchDynamicConfigService.isSearchSuggestionTipsOpen(); 186 return searchDynamicConfigService.isSearchSuggestionTipsOpen();
187 } 187 }
188 188
189 -  
190 - /**  
191 - * pc的商品列表页  
192 - *  
193 - * @param paramMap  
194 - * @return  
195 - */  
196 -  
197 -  
198 } 189 }
@@ -17,7 +17,21 @@ public abstract class AbstractSceneService { @@ -17,7 +17,21 @@ public abstract class AbstractSceneService {
17 protected static final String STANDARD = "standard"; 17 protected static final String STANDARD = "standard";
18 18
19 protected Map<String, String> newParamMap(Map<String, String> paramMap) { 19 protected Map<String, String> newParamMap(Map<String, String> paramMap) {
20 - return new HashMap<String, String>(paramMap); 20 + return new HashMap<>(paramMap);
  21 + }
  22 +
  23 + /**
  24 + * 去除非正常商品的显示
  25 + * @param paramMap
  26 + */
  27 + protected void filterNotNormalToMap(Map<String, String> paramMap) {
  28 + paramMap.put(SearchRequestParams.PARAM_SEARCH_ISLIMITED, "N");// 不支持限定
  29 + paramMap.put(SearchRequestParams.PARAM_SEARCH_CONTAIN_SECKILL, "N");// 不支持秒杀
  30 + paramMap.put(SearchRequestParams.PARAM_SEARCH_ISADVANCE, "N");// 不支持预售
  31 + paramMap.put(SearchRequestParams.PARAM_SEARCH_BUNDLETYPE, "0");// 不支持套餐
  32 + paramMap.put(SearchRequestParams.PARAM_SEARCH_ISLIMITEDBUY, "N");// 不支持限购
  33 + paramMap.put(SearchRequestParams.PARAM_SEARCH_ISDESPOSITADVANCE, "N");// 不支持定金预售
  34 + paramMap.put(SearchRequestParams.PARAM_SEARCH_ISLIMITTIMEADVANCE, "N");// 不支持定金促销
21 } 35 }
22 36
23 /** 37 /**
@@ -48,10 +62,6 @@ public abstract class AbstractSceneService { @@ -48,10 +62,6 @@ public abstract class AbstractSceneService {
48 return page; 62 return page;
49 } 63 }
50 64
51 - protected String getuid(Map<String, String> paramMap) {  
52 - return MapUtils.getString(paramMap, "uid", "0");  
53 - }  
54 -  
55 public abstract void addParamsToParamMap(Map<String, String> paramMap); 65 public abstract void addParamsToParamMap(Map<String, String> paramMap);
56 66
57 public abstract String pageId(); 67 public abstract String pageId();
  1 +package com.yoho.search.service.scene.miniapp;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.yoho.search.base.utils.SearchPageIdDefine;
  5 +import com.yoho.search.common.utils.SearchApiResultUtils;
  6 +import com.yoho.search.models.SearchApiResult;
  7 +import com.yoho.search.service.base.SearchRequestParams;
  8 +import com.yoho.search.service.helper.SearchCommonHelper;
  9 +import com.yoho.search.service.helper.SearchKeyWordHelper;
  10 +import com.yoho.search.service.list.FuzzySceneProductListService;
  11 +import com.yoho.search.service.scene.FuzzySceneService;
  12 +import com.yoho.search.service.scene.common.AbstractSceneService;
  13 +import com.yoho.search.service.scene.common.SceneRecommendBrandsService;
  14 +import com.yoho.search.service.scene.common.SceneSelectionsService;
  15 +import org.apache.commons.lang.StringUtils;
  16 +import org.slf4j.Logger;
  17 +import org.slf4j.LoggerFactory;
  18 +import org.springframework.beans.factory.annotation.Autowired;
  19 +import org.springframework.stereotype.Service;
  20 +
  21 +import java.util.Map;
  22 +
  23 +@Service
  24 +public class MiniappFuzzySceneService extends AbstractSceneService {
  25 +
  26 + private static final Logger logger = LoggerFactory.getLogger(MiniappFuzzySceneService.class);
  27 +
  28 + @Autowired
  29 + private SearchCommonHelper searchCommonHelper;
  30 + @Autowired
  31 + private SearchKeyWordHelper searchKeyWordService;
  32 + @Autowired
  33 + private FuzzySceneProductListService fuzzySceneProductListService;
  34 + @Autowired
  35 + private FuzzySceneService fuzzySceneService;
  36 + @Autowired
  37 + private SceneSelectionsService sceneSelectionsService;
  38 + @Autowired
  39 + private SceneRecommendBrandsService sceneRecommendBrandsService;
  40 +
  41 + @Override
  42 + public String pageId() {
  43 + return SearchPageIdDefine.PAGE_ID_SEARCH;
  44 + }
  45 +
  46 + @Override
  47 + public void addParamsToParamMap(Map<String, String> paramMap) {
  48 + super.addDefaultParamsToParamMap(paramMap);
  49 + super.filterNotNormalToMap(paramMap);
  50 + paramMap.put(SearchRequestParams.PARAM_SEARCH_NEED_SUGGESTION, "Y");// 返回建议词
  51 + }
  52 +
  53 + /**
  54 + * @1、返回商品列表
  55 + * @2、数量太多则返回建议词
  56 + */
  57 + @Override
  58 + public SearchApiResult productList(Map<String, String> paramMap) {
  59 + try {
  60 + // 1、参数校验
  61 + if (StringUtils.isBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_QUERY))) {
  62 + return new SearchApiResult().setCode(400).setMessage("请传query参数");
  63 + }
  64 + // 2、添加默认参数
  65 + this.addParamsToParamMap(paramMap);
  66 +
  67 + // 3、获取列表
  68 + SearchApiResult productListResult = fuzzySceneProductListService.productList(paramMap);
  69 +
  70 + // 4、加入建议词
  71 + fuzzySceneService.addSuggestion(productListResult, paramMap);
  72 +
  73 + // 5、模糊搜索页记录关键字对应的查询结果
  74 + String queryWord = paramMap.get("query");
  75 + if (!StringUtils.isBlank(queryWord) && !searchCommonHelper.isQuerySknOrSku(queryWord)) {
  76 + long total = ((JSONObject) productListResult.getData()).getLongValue("total");
  77 + searchKeyWordService.recordKeyWordByResultCount(queryWord, total);
  78 + }
  79 + //6、返回结果
  80 + return productListResult;
  81 + } catch (Exception e) {
  82 + logger.error(e.getMessage(), e);
  83 + return SearchApiResultUtils.errorSearchApiResult("SappFuzzySceneService productList Exception", paramMap, e);
  84 + }
  85 + }
  86 +
  87 + @Override
  88 + public SearchApiResult aggregations(Map<String, String> paramMap) {
  89 + try {
  90 + // 1、参数校验
  91 + if (StringUtils.isBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_QUERY))) {
  92 + return new SearchApiResult().setCode(400).setMessage("请传query参数");
  93 + }
  94 + // 1、添加默认参数
  95 + this.addParamsToParamMap(paramMap);
  96 + // 2、返回聚合结果
  97 + SearchApiResult result = sceneSelectionsService.aggregations(paramMap);
  98 + if(result!=null){
  99 + sceneRecommendBrandsService.getRecommendBrands(paramMap, result);
  100 + }
  101 + return result;
  102 + } catch (Exception e) {
  103 + logger.error(e.getMessage(), e);
  104 + return new SearchApiResult().setData(null).setMessage("SappFuzzySceneService Aggregations Exception").setCode(500);
  105 + }
  106 + }
  107 +
  108 +}