Authored by hugufei

新列表召回代码优化

@@ -2,175 +2,76 @@ package com.yoho.search.recall.scene; @@ -2,175 +2,76 @@ package com.yoho.search.recall.scene;
2 2
3 import com.alibaba.fastjson.JSONObject; 3 import com.alibaba.fastjson.JSONObject;
4 import com.yoho.search.models.SearchApiResult; 4 import com.yoho.search.models.SearchApiResult;
  5 +import com.yoho.search.recall.scene.component.*;
5 import com.yoho.search.recall.scene.models.*; 6 import com.yoho.search.recall.scene.models.*;
6 import com.yoho.search.recall.scene.persional.PersionalFactor; 7 import com.yoho.search.recall.scene.persional.PersionalFactor;
7 import com.yoho.search.recall.scene.persional.RecallPersionalService; 8 import com.yoho.search.recall.scene.persional.RecallPersionalService;
8 -import com.yoho.search.recall.scene.request.BrandRecallRequestBuilder;  
9 -import com.yoho.search.recall.scene.request.CommonRecallRequestBuilder;  
10 -import com.yoho.search.recall.scene.request.SortPriceRecallRequestBuilder;  
11 -import com.yoho.search.recall.scene.strategy.StrategyNameEnum;  
12 -import com.yoho.search.recall.sort.helper.RecallServiceHelper;  
13 -import com.yoho.search.service.helper.SearchCommonHelper;  
14 -import com.yoho.search.service.helper.SearchServiceHelper;  
15 import org.apache.commons.collections.MapUtils; 9 import org.apache.commons.collections.MapUtils;
16 -import org.apache.commons.lang.StringUtils;  
17 -import org.elasticsearch.index.query.BoolQueryBuilder;  
18 -import org.elasticsearch.index.query.QueryBuilder; 10 +import org.slf4j.Logger;
  11 +import org.slf4j.LoggerFactory;
19 import org.springframework.beans.factory.annotation.Autowired; 12 import org.springframework.beans.factory.annotation.Autowired;
20 import org.springframework.stereotype.Component; 13 import org.springframework.stereotype.Component;
21 14
22 -import java.util.ArrayList;  
23 -import java.util.HashMap;  
24 import java.util.List; 15 import java.util.List;
25 import java.util.Map; 16 import java.util.Map;
26 17
27 @Component 18 @Component
28 public class SceneRecallService { 19 public class SceneRecallService {
29 20
  21 + private static final Logger logger = LoggerFactory.getLogger(SceneRecallService.class);
  22 +
30 @Autowired 23 @Autowired
31 - private SearchServiceHelper searchServiceHelepr; 24 + private RecallParamsBuilder recallParamsBuilder;
32 @Autowired 25 @Autowired
33 private RecallPersionalService recallPersionalService; 26 private RecallPersionalService recallPersionalService;
34 @Autowired 27 @Autowired
35 - private CommonRecallRequestBuilder commonRequestBuilder;  
36 - @Autowired  
37 - private BrandRecallRequestBuilder brandRequestBuilder;  
38 - @Autowired  
39 - private SortPriceRecallRequestBuilder sortPriceRequestBuilder; 28 + private BatchRequestsBuilder batchRequestsBuilder;
40 @Autowired 29 @Autowired
41 - private RecallCommonService recallCommonService; 30 + private BatchRecallComponent bacthRecallComponent;
42 @Autowired 31 @Autowired
43 - private RecallServiceHelper recallServiceHelper; 32 + private BatchResponseBuilder batchResponseBuilder;
44 @Autowired 33 @Autowired
45 - private SearchCommonHelper searchCommonHelper; 34 + private RecallResultBuilder recallResultBuilder;
46 35
47 public SearchApiResult sceneRecall(Map<String, String> paramMap) { 36 public SearchApiResult sceneRecall(Map<String, String> paramMap) {
48 try { 37 try {
49 //1、分页参数验证 38 //1、分页参数验证
50 - int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));  
51 - int page = StringUtils.isBlank(paramMap.get("page")) ? 1 : Integer.parseInt(paramMap.get("page")); 39 + int page = MapUtils.getIntValue(paramMap, "page", 10);
  40 + int pageSize = MapUtils.getIntValue(paramMap, "viewNum", 10);
52 if (page < 1 || pageSize < 0 || page * pageSize > 1000000) { 41 if (page < 1 || pageSize < 0 || page * pageSize > 1000000) {
53 return new SearchApiResult().setCode(400).setMessage("分页参数不合法"); 42 return new SearchApiResult().setCode(400).setMessage("分页参数不合法");
54 } 43 }
55 //2、构造召回相关参数 44 //2、构造召回相关参数
56 - RecallParams recallParams = this.buildRecallParams(paramMap);  
57 - //3、执行召回  
58 - RecallResponseBatch recallResponseBatch = this.doBatchRecall(recallParams);  
59 - //4、构造返回结果 45 + RecallParams recallParams = recallParamsBuilder.buildRecallParams(paramMap);
  46 + //3、获取个性化因子
  47 + PersionalFactor persionalFactor = recallPersionalService.queryPersionalFactor(recallParams);
  48 + //4、执行召回
  49 + RecallResult recallResult = this.doRecall(recallParams, persionalFactor);
  50 + //TODO
  51 + //5、构造返回结果
60 JSONObject dataMap = new JSONObject(); 52 JSONObject dataMap = new JSONObject();
61 - dataMap.put("total", recallResponseBatch.getTotal());  
62 - dataMap.put("page", page);  
63 - dataMap.put("page_size", pageSize);  
64 - dataMap.put("page_total", searchCommonHelper.getTotalPage(recallResponseBatch.getTotal(), pageSize));  
65 - dataMap.put("product_list", recallResponseBatch.getSknList());  
66 - dataMap.put("product_list_size", recallResponseBatch.getSknList().size()); 53 + dataMap.put("total", recallResult.getTotal());
  54 + dataMap.put("page", recallResult.getPage());
  55 + dataMap.put("page_size", recallResult.getPageSize());
  56 + dataMap.put("page_total", recallResult.getPageTotal());
  57 + dataMap.put("product_list", recallResult.getSknList());
67 return new SearchApiResult().setData(dataMap); 58 return new SearchApiResult().setData(dataMap);
68 } catch (Exception e) { 59 } catch (Exception e) {
69 - e.printStackTrace(); 60 + logger.error(e.getMessage(), e);
70 return new SearchApiResult().setData(null).setCode(500).setMessage("Exception"); 61 return new SearchApiResult().setData(null).setCode(500).setMessage("Exception");
71 } 62 }
72 } 63 }
73 64
74 - private RecallParams buildRecallParams(Map<String, String> paramMap) throws Exception {  
75 - //1、获取连接中的query和filter参数  
76 - QueryBuilder query = searchServiceHelepr.constructQueryBuilder(paramMap);  
77 - BoolQueryBuilder filter = searchServiceHelepr.constructFilterBuilder(paramMap, null);  
78 - ParamQueryFilter paramQueryFilter = new ParamQueryFilter(query,filter);  
79 -  
80 - //2、获取firstSkn参数  
81 - List<String> firstProductSkns = recallServiceHelper.getFirstProductSkns(paramMap);  
82 -  
83 - //3、虎丘分页参数  
84 - int pageSize = MapUtils.getIntValue(paramMap, "viewNum", 10);  
85 -  
86 - //4、获取uid或udid  
87 - int uid = MapUtils.getIntValue(paramMap, "uid", 1);  
88 - String udid = MapUtils.getString(paramMap, "udid", "");  
89 -  
90 - return new RecallParams(paramQueryFilter, firstProductSkns, pageSize, uid, udid);  
91 - }  
92 -  
93 - private RecallResponseBatch doBatchRecall(RecallParams param) {  
94 - //1、构造召回请求  
95 - List<RecallRequest> allRequests = this.buildRecallRequests(param); 65 + private RecallResult doRecall(RecallParams param, PersionalFactor persionalFactor) {
  66 + //1、构造请求
  67 + List<RecallRequest> batchRequests = batchRequestsBuilder.buildBatchRequests(param, persionalFactor);
96 //2、批量召回 68 //2、批量召回
97 - List<RecallRequestResponse> requestResponses = recallCommonService.batchRecallAndCache(allRequests);  
98 - //3、从兜底类型中获取总数  
99 - long total = this.getTotalCount(requestResponses);  
100 - //4、获取召回的skn  
101 - List<RecallResponseBatch.SknResult> sknResults = this.distinctRecallSkn(requestResponses);  
102 - //5、构造返回结果  
103 - return new RecallResponseBatch(total, sknResults);  
104 - }  
105 -  
106 - private List<RecallRequest> buildRecallRequests(RecallParams param) {  
107 - //1、构造召回请求  
108 - List<RecallRequest> allRequests = new ArrayList<>();  
109 - //2、构造非个性化的请求  
110 - List<RecallRequest> commonRequests = commonRequestBuilder.buildCommonRecallRequests(param.getParamQueryFilter(), param.getFirstProductSkns(), param.getPageSize());  
111 - allRequests.addAll(commonRequests);  
112 - //3、获取个性化因子  
113 - PersionalFactor persionalFactor = recallPersionalService.queryPersionalFactor(param.getParamQueryFilter(), param.getUid(), param.getUdid());  
114 - //4、构建个性化品牌的召回请求  
115 - List<RecallRequest> brandRequests = brandRequestBuilder.buildBrandRecallRequests(param.getParamQueryFilter(), persionalFactor.getBrandIds());  
116 - allRequests.addAll(brandRequests);  
117 - //5、构建个性化品牌的召回请求  
118 - List<RecallRequest> sortPriceRequests = sortPriceRequestBuilder.buildSortPriceRecallRequests(param.getParamQueryFilter(), persionalFactor.getSortPriceAreas());  
119 - allRequests.addAll(sortPriceRequests);  
120 - return allRequests;  
121 - }  
122 -  
123 - /**  
124 - * 从兜底类型中获取总数  
125 - *  
126 - * @param requestResponses  
127 - * @return  
128 - */  
129 - private long getTotalCount(List<RecallRequestResponse> requestResponses) {  
130 - long total = 0;  
131 - for (RecallRequestResponse requestResponse : requestResponses) {  
132 - RecallRequest request = requestResponse.getRequest();  
133 - RecallResponse response = requestResponse.getResponse();  
134 - if (request ==null || response == null) {  
135 - continue;  
136 - }  
137 - if (StrategyNameEnum.COMMON.name().equalsIgnoreCase(request.requestType())){  
138 - total = response.getTotal();  
139 - break;  
140 - }  
141 - }  
142 - return total;  
143 - }  
144 -  
145 - /**  
146 - * 召回结果去重  
147 - *  
148 - * @param requestResponses  
149 - * @return  
150 - */  
151 - private List<RecallResponseBatch.SknResult> distinctRecallSkn(List<RecallRequestResponse> requestResponses) {  
152 - List<RecallResponseBatch.SknResult> sknResults = new ArrayList<>();  
153 - Map<Integer,List<String>> sknRequestMaps = new HashMap<>();  
154 - for (RecallRequestResponse requestResponse : requestResponses) {  
155 - RecallRequest request = requestResponse.getRequest();  
156 - RecallResponse response = requestResponse.getResponse();  
157 - if (request==null || response == null || response.getSkns()==null){  
158 - continue;  
159 - }  
160 - for (RecallResponse.RecallSkn recallSkn : response.getSkns()) {  
161 - List<String> requestTypes = sknRequestMaps.get(recallSkn.getSkn());  
162 - if(requestTypes==null){  
163 - sknResults.add(new RecallResponseBatch.SknResult(recallSkn));  
164 - requestTypes = new ArrayList<>();  
165 - sknRequestMaps.put(recallSkn.getSkn(),requestTypes);  
166 - }  
167 - requestTypes.add(request.requestType());  
168 - }  
169 - }  
170 - for (RecallResponseBatch.SknResult sknResult:sknResults) {  
171 - sknResult.setRequestTypes(sknRequestMaps.get(sknResult.getProductSkn()));  
172 - }  
173 - return sknResults; 69 + List<RecallRequestResponse> requestResponses = bacthRecallComponent.batchRecallAndCache(batchRequests);
  70 + //3、获取skn列表[去重]
  71 + RecallResponseBatch recallResponseBatch = batchResponseBuilder.buildRecallResponseBatch(requestResponses);
  72 + //4、构造真实结果[排序,截取skn]
  73 + RecallResult recallResult = recallResultBuilder.builderRecallResult(recallResponseBatch, param, persionalFactor);
  74 + return recallResult;
174 } 75 }
175 76
176 } 77 }
1 -package com.yoho.search.recall.scene; 1 +package com.yoho.search.recall.scene.component;
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.CollectionUtils;
@@ -21,7 +21,7 @@ import java.util.List; @@ -21,7 +21,7 @@ import java.util.List;
21 import java.util.Map; 21 import java.util.Map;
22 22
23 @Component 23 @Component
24 -public class RecallCommonService { 24 +public class BatchRecallComponent {
25 25
26 @Autowired 26 @Autowired
27 private SearchRedis searchRedis; 27 private SearchRedis searchRedis;
@@ -31,13 +31,13 @@ public class RecallCommonService { @@ -31,13 +31,13 @@ public class RecallCommonService {
31 /** 31 /**
32 * 批量召回入口 32 * 批量召回入口
33 * 33 *
34 - * @param requests 34 + * @param batchRequests
35 * @return 35 * @return
36 */ 36 */
37 - public List<RecallRequestResponse> batchRecallAndCache(final List<RecallRequest> requests) { 37 + public List<RecallRequestResponse> batchRecallAndCache(final List<RecallRequest> batchRequests) {
38 38
39 //1、先从缓存中获取数据,并且构建返回结果对象 39 //1、先从缓存中获取数据,并且构建返回结果对象
40 - final List<RecallRequestResponse> results = this.queryResultFromCache(requests); 40 + final List<RecallRequestResponse> results = this.queryResultFromCache(batchRequests);
41 41
42 //2、构造未命中缓存的请求-最多透传x个 42 //2、构造未命中缓存的请求-最多透传x个
43 final List<RecallRequest> notCachedRequests = this.buildNotCachedRequests(results, 10); 43 final List<RecallRequest> notCachedRequests = this.buildNotCachedRequests(results, 10);
  1 +package com.yoho.search.recall.scene.component;
  2 +
  3 +import com.yoho.search.recall.scene.models.RecallParams;
  4 +import com.yoho.search.recall.scene.models.RecallRequest;
  5 +import com.yoho.search.recall.scene.persional.PersionalFactor;
  6 +import com.yoho.search.recall.scene.request.BrandRecallRequestBuilder;
  7 +import com.yoho.search.recall.scene.request.CommonRecallRequestBuilder;
  8 +import com.yoho.search.recall.scene.request.SortPriceRecallRequestBuilder;
  9 +import org.springframework.beans.factory.annotation.Autowired;
  10 +import org.springframework.stereotype.Component;
  11 +
  12 +import java.util.ArrayList;
  13 +import java.util.List;
  14 +
  15 +@Component
  16 +public class BatchRequestsBuilder {
  17 +
  18 + @Autowired
  19 + private CommonRecallRequestBuilder commonRequestBuilder;
  20 + @Autowired
  21 + private BrandRecallRequestBuilder brandRequestBuilder;
  22 + @Autowired
  23 + private SortPriceRecallRequestBuilder sortPriceRequestBuilder;
  24 +
  25 + /**
  26 + * 批量请求构造器
  27 + * @param param
  28 + * @param persionalFactor
  29 + * @return
  30 + */
  31 + public List<RecallRequest> buildBatchRequests(RecallParams param,PersionalFactor persionalFactor) {
  32 + //1、构造召回请求
  33 + List<RecallRequest> allRequests = new ArrayList<>();
  34 + //2、构造非个性化的请求
  35 + List<RecallRequest> commonRequests = commonRequestBuilder.buildCommonRecallRequests(param.getParamQueryFilter(), param.getFirstProductSkns(), param.getPageSize());
  36 + allRequests.addAll(commonRequests);
  37 + //4、构建个性化品牌的召回请求
  38 + List<RecallRequest> brandRequests = brandRequestBuilder.buildBrandRecallRequests(param.getParamQueryFilter(), persionalFactor.getBrandIds());
  39 + allRequests.addAll(brandRequests);
  40 + //5、构建个性化品牌的召回请求
  41 + List<RecallRequest> sortPriceRequests = sortPriceRequestBuilder.buildSortPriceRecallRequests(param.getParamQueryFilter(), persionalFactor.getSortPriceAreas());
  42 + allRequests.addAll(sortPriceRequests);
  43 + return allRequests;
  44 + }
  45 +
  46 +}
  1 +package com.yoho.search.recall.scene.component;
  2 +
  3 +import com.yoho.search.recall.scene.models.*;
  4 +import com.yoho.search.recall.scene.persional.PersionalFactor;
  5 +import com.yoho.search.recall.scene.strategy.StrategyNameEnum;
  6 +import org.springframework.stereotype.Component;
  7 +
  8 +import java.util.ArrayList;
  9 +import java.util.HashMap;
  10 +import java.util.List;
  11 +import java.util.Map;
  12 +
  13 +@Component
  14 +public class BatchResponseBuilder {
  15 +
  16 + /**
  17 + * 召回结果构造器
  18 + * @param requestResponses
  19 + * @return
  20 + */
  21 + public RecallResponseBatch buildRecallResponseBatch(List<RecallRequestResponse> requestResponses){
  22 + //1、从兜底类型中获取总数
  23 + long total = this.getTotalCount(requestResponses);
  24 + //2、获取召回的skn
  25 + List<RecallResponseBatch.SknResult> sknResults = this.distinctRecallSkn(requestResponses);
  26 + //3、返回召回结果
  27 + return new RecallResponseBatch(total, sknResults);
  28 + }
  29 +
  30 + /**
  31 + * 从兜底类型中获取总数
  32 + *
  33 + * @param requestResponses
  34 + * @return
  35 + */
  36 + private long getTotalCount(List<RecallRequestResponse> requestResponses) {
  37 + long total = 0;
  38 + for (RecallRequestResponse requestResponse : requestResponses) {
  39 + RecallRequest request = requestResponse.getRequest();
  40 + RecallResponse response = requestResponse.getResponse();
  41 + if (request ==null || response == null) {
  42 + continue;
  43 + }
  44 + if (StrategyNameEnum.COMMON.name().equalsIgnoreCase(request.requestType())){
  45 + total = response.getTotal();
  46 + break;
  47 + }
  48 + }
  49 + return total;
  50 + }
  51 +
  52 + /**
  53 + * 召回结果去重
  54 + *
  55 + * @param requestResponses
  56 + * @return
  57 + */
  58 + private List<RecallResponseBatch.SknResult> distinctRecallSkn(List<RecallRequestResponse> requestResponses) {
  59 + List<RecallResponseBatch.SknResult> sknResults = new ArrayList<>();
  60 + Map<Integer,List<String>> sknRequestMaps = new HashMap<>();
  61 + for (RecallRequestResponse requestResponse : requestResponses) {
  62 + RecallRequest request = requestResponse.getRequest();
  63 + RecallResponse response = requestResponse.getResponse();
  64 + if (request==null || response == null || response.getSkns()==null){
  65 + continue;
  66 + }
  67 + for (RecallResponse.RecallSkn recallSkn : response.getSkns()) {
  68 + List<String> requestTypes = sknRequestMaps.get(recallSkn.getSkn());
  69 + if(requestTypes==null){
  70 + sknResults.add(new RecallResponseBatch.SknResult(recallSkn));
  71 + requestTypes = new ArrayList<>();
  72 + sknRequestMaps.put(recallSkn.getSkn(),requestTypes);
  73 + }
  74 + requestTypes.add(request.requestType());
  75 + }
  76 + }
  77 + for (RecallResponseBatch.SknResult sknResult:sknResults) {
  78 + sknResult.setRequestTypes(sknRequestMaps.get(sknResult.getProductSkn()));
  79 + }
  80 + return sknResults;
  81 + }
  82 +
  83 +}
  1 +package com.yoho.search.recall.scene.component;
  2 +
  3 +import com.yoho.search.recall.scene.models.ParamQueryFilter;
  4 +import com.yoho.search.recall.scene.models.RecallParams;
  5 +import com.yoho.search.recall.sort.helper.RecallServiceHelper;
  6 +import com.yoho.search.service.helper.SearchServiceHelper;
  7 +import org.apache.commons.collections.MapUtils;
  8 +import org.elasticsearch.index.query.BoolQueryBuilder;
  9 +import org.elasticsearch.index.query.QueryBuilder;
  10 +import org.springframework.beans.factory.annotation.Autowired;
  11 +import org.springframework.stereotype.Component;
  12 +
  13 +import java.util.List;
  14 +import java.util.Map;
  15 +
  16 +@Component
  17 +public class RecallParamsBuilder {
  18 +
  19 + @Autowired
  20 + private SearchServiceHelper searchServiceHelepr;
  21 + @Autowired
  22 + private RecallServiceHelper recallServiceHelper;
  23 +
  24 + public RecallParams buildRecallParams(Map<String, String> paramMap) throws Exception {
  25 + //1、获取链接中的query和filter参数
  26 + QueryBuilder query = searchServiceHelepr.constructQueryBuilder(paramMap);
  27 + BoolQueryBuilder filter = searchServiceHelepr.constructFilterBuilder(paramMap, null);
  28 + ParamQueryFilter queryFilter = new ParamQueryFilter(query,filter);
  29 +
  30 + //2、获取分页参数
  31 + int page = MapUtils.getIntValue(paramMap, "page", 1);
  32 + int pageSize = MapUtils.getIntValue(paramMap, "viewNum", 10);
  33 +
  34 + //3、获取firstSkn参数
  35 + List<String> firstProductSkns = recallServiceHelper.getFirstProductSkns(paramMap);
  36 +
  37 + //4、获取uid或udid
  38 + int uid = MapUtils.getIntValue(paramMap, "uid", 1);
  39 + String udid = MapUtils.getString(paramMap, "udid", "");
  40 +
  41 + return new RecallParams(queryFilter,page,pageSize, firstProductSkns , uid, udid);
  42 + }
  43 +}
  1 +package com.yoho.search.recall.scene.component;
  2 +
  3 +import com.yoho.search.recall.scene.models.RecallParams;
  4 +import com.yoho.search.recall.scene.models.RecallResponseBatch;
  5 +import com.yoho.search.recall.scene.models.RecallResult;
  6 +import com.yoho.search.recall.scene.persional.PersionalFactor;
  7 +import com.yoho.search.recall.scene.strategy.StrategyNameEnum;
  8 +import com.yoho.search.service.base.ProductListSortKey;
  9 +import com.yoho.search.service.base.ProductListSortService;
  10 +import com.yoho.search.service.helper.SearchCommonHelper;
  11 +import org.springframework.beans.factory.annotation.Autowired;
  12 +import org.springframework.stereotype.Component;
  13 +
  14 +import java.util.ArrayList;
  15 +import java.util.Collections;
  16 +import java.util.Comparator;
  17 +import java.util.List;
  18 +
  19 +@Component
  20 +public class RecallResultBuilder {
  21 +
  22 + @Autowired
  23 + private SearchCommonHelper searchCommonHelper;
  24 + @Autowired
  25 + private ProductListSortService productListSortService;
  26 +
  27 + public RecallResult builderRecallResult(RecallResponseBatch recallResponseBatch, RecallParams param, PersionalFactor persionalFactor){
  28 + //1、构造结果中的分页信息
  29 + final long total = recallResponseBatch.getTotal();
  30 + final int page = param.getPage();
  31 + final int pageSize = param.getPageSize();
  32 + final long pageTotal = searchCommonHelper.getTotalPage(total,pageSize);
  33 +
  34 + //2、获取召回结果中的最大整数页码
  35 + List<RecallResponseBatch.SknResult> sknResultList = recallResponseBatch.getSknList();
  36 +
  37 + //3、计算得分
  38 + this.doCalScore(sknResultList,persionalFactor);
  39 +
  40 + //4、排序
  41 + Collections.sort(sknResultList, new Comparator<RecallResponseBatch.SknResult>() {
  42 + @Override
  43 + public int compare(RecallResponseBatch.SknResult o1, RecallResponseBatch.SknResult o2) {
  44 + return o2.getScore().compareTo(o1.getScore());// 大的排前面
  45 + }
  46 + });
  47 +
  48 + //5、品牌品类平衡
  49 + sknResultList = productListSortService.sortProductList(sknResultList, new ProductListSortKey<RecallResponseBatch.SknResult>() {
  50 + @Override
  51 + public String getSortKey(RecallResponseBatch.SknResult product) {
  52 + return new StringBuilder().append(product.getBrandId()).append("_").append(product.getMiddleSortId()).toString();
  53 + }
  54 + @Override
  55 + public int getMaxCount() {
  56 + return 2;
  57 + }
  58 + });
  59 +
  60 + //6、处理直通车
  61 +
  62 + //7、截取整数页
  63 + int recallMaxPage = (sknResultList.size() / pageSize);
  64 + if (recallMaxPage == 0) {
  65 + recallMaxPage = 1;
  66 + }
  67 + if (recallMaxPage > 5) {
  68 + recallMaxPage = 5;
  69 + }
  70 +
  71 + //8、判断当前页码是否在召回结果中
  72 + int realPage = page;
  73 + List<Integer> sknList = new ArrayList<>();
  74 + if(page > recallMaxPage) {
  75 + realPage = page - recallMaxPage;
  76 + sknList = this.getSknList(sknResultList);
  77 + }else{
  78 +
  79 + }
  80 + return new RecallResult(total,page,pageSize,pageTotal,realPage,sknList);
  81 + }
  82 +
  83 + private void doCalScore(List<RecallResponseBatch.SknResult> sknResultList,PersionalFactor persionalFactor) {
  84 + String userFactor = persionalFactor.getUserFactor();
  85 + for (RecallResponseBatch.SknResult sknResult : sknResultList) {
  86 + if (sknResult.getRequestTypes().contains(StrategyNameEnum.FIRST_PRODUCT_SKN.name())) {
  87 + sknResult.setScore(10000d);// firstSkn排第一个
  88 + sknResult.setScore(Math.random());
  89 + } else {
  90 + sknResult.setScore(Math.random());
  91 + }
  92 + }
  93 + }
  94 +
  95 + private List<Integer> getSknList(List<RecallResponseBatch.SknResult> sknResultList){
  96 + List<Integer> sknList = new ArrayList<>();
  97 + for (RecallResponseBatch.SknResult sknResult:sknResultList){
  98 + sknList.add(sknResult.getProductSkn());
  99 + }
  100 + return sknList;
  101 + }
  102 +
  103 +}
1 package com.yoho.search.recall.scene.models; 1 package com.yoho.search.recall.scene.models;
2 2
3 -import org.elasticsearch.index.query.BoolQueryBuilder;  
4 -import org.elasticsearch.index.query.QueryBuilder;  
5 -  
6 import java.util.List; 3 import java.util.List;
7 4
8 public class RecallParams { 5 public class RecallParams {
9 6
10 - private ParamQueryFilter paramQueryFilter;  
11 - private List<String> firstProductSkns;  
12 - private int pageSize;  
13 - private int uid;  
14 - private String udid; 7 + private final ParamQueryFilter paramQueryFilter;
  8 + private final int page;
  9 + private final int pageSize;
  10 + private final List<String> firstProductSkns;
  11 + private final int uid;
  12 + private final String udid;
15 13
16 - public RecallParams(ParamQueryFilter paramQueryFilter, List<String> firstProductSkns, int pageSize, int uid, String udid) { 14 + public RecallParams(ParamQueryFilter paramQueryFilter,int page, int pageSize,List<String> firstProductSkns, int uid, String udid) {
17 this.paramQueryFilter = paramQueryFilter; 15 this.paramQueryFilter = paramQueryFilter;
18 this.firstProductSkns = firstProductSkns; 16 this.firstProductSkns = firstProductSkns;
  17 + this.page = page;
19 this.pageSize = pageSize; 18 this.pageSize = pageSize;
20 this.uid = uid; 19 this.uid = uid;
21 this.udid = udid; 20 this.udid = udid;
@@ -25,8 +24,8 @@ public class RecallParams { @@ -25,8 +24,8 @@ public class RecallParams {
25 return paramQueryFilter; 24 return paramQueryFilter;
26 } 25 }
27 26
28 - public List<String> getFirstProductSkns() {  
29 - return firstProductSkns; 27 + public int getPage() {
  28 + return page;
30 } 29 }
31 30
32 public int getPageSize() { 31 public int getPageSize() {
@@ -41,4 +40,8 @@ public class RecallParams { @@ -41,4 +40,8 @@ public class RecallParams {
41 return udid; 40 return udid;
42 } 41 }
43 42
  43 + public List<String> getFirstProductSkns() {
  44 + return firstProductSkns;
  45 + }
  46 +
44 } 47 }
@@ -7,7 +7,7 @@ public class RecallResponseBatch { @@ -7,7 +7,7 @@ public class RecallResponseBatch {
7 private long total; 7 private long total;
8 private List<SknResult> sknList; 8 private List<SknResult> sknList;
9 9
10 - public RecallResponseBatch(long total, List<SknResult> sknList) { 10 + public RecallResponseBatch(long total,List<SknResult> sknList) {
11 this.total = total; 11 this.total = total;
12 this.sknList = sknList; 12 this.sknList = sknList;
13 } 13 }
@@ -26,6 +26,8 @@ public class RecallResponseBatch { @@ -26,6 +26,8 @@ public class RecallResponseBatch {
26 private Integer brandId; 26 private Integer brandId;
27 private Integer middleSortId; 27 private Integer middleSortId;
28 private List<String> requestTypes; 28 private List<String> requestTypes;
  29 + private String factor;
  30 + private Double score;
29 31
30 public SknResult(RecallResponse.RecallSkn recallSkn) { 32 public SknResult(RecallResponse.RecallSkn recallSkn) {
31 this.productSkn = recallSkn.getSkn(); 33 this.productSkn = recallSkn.getSkn();
@@ -52,6 +54,22 @@ public class RecallResponseBatch { @@ -52,6 +54,22 @@ public class RecallResponseBatch {
52 public void setRequestTypes(List<String> requestTypes) { 54 public void setRequestTypes(List<String> requestTypes) {
53 this.requestTypes = requestTypes; 55 this.requestTypes = requestTypes;
54 } 56 }
  57 +
  58 + public Double getScore() {
  59 + return score;
  60 + }
  61 +
  62 + public void setScore(Double score) {
  63 + this.score = score;
  64 + }
  65 +
  66 + public String getFactor() {
  67 + return factor;
  68 + }
  69 +
  70 + public void setFactor(String factor) {
  71 + this.factor = factor;
  72 + }
55 } 73 }
56 74
57 } 75 }
  1 +package com.yoho.search.recall.scene.models;
  2 +
  3 +import java.util.List;
  4 +
  5 +public class RecallResult {
  6 + private final long total;
  7 + private final int page;
  8 + private final int pageSize;
  9 + private final long pageTotal;
  10 + private final int realPage;
  11 + private final List<Integer> sknList;
  12 +
  13 + public RecallResult(long total,int page, int pageSize,long pageTotal, int realPage,List<Integer> sknList) {
  14 + this.total = total;
  15 + this.page = page;
  16 + this.pageSize = pageSize;
  17 + this.pageTotal = pageTotal;
  18 + this.realPage = realPage;
  19 + this.sknList = sknList;
  20 + }
  21 +
  22 + public long getTotal() {
  23 + return total;
  24 + }
  25 +
  26 + public int getPage() {
  27 + return page;
  28 + }
  29 +
  30 + public int getPageSize() {
  31 + return pageSize;
  32 + }
  33 +
  34 + public long getPageTotal() {
  35 + return pageTotal;
  36 + }
  37 +
  38 + public int getRealPage() {
  39 + return realPage;
  40 + }
  41 +
  42 + public List<Integer> getSknList() {
  43 + return sknList;
  44 + }
  45 +}
@@ -9,13 +9,15 @@ public class PersionalFactor implements Serializable{ @@ -9,13 +9,15 @@ public class PersionalFactor implements Serializable{
9 9
10 private List<Integer> brandIds; 10 private List<Integer> brandIds;
11 private List<SortPriceArea> sortPriceAreas; 11 private List<SortPriceArea> sortPriceAreas;
  12 + private String userFactor;
12 13
13 public PersionalFactor() { 14 public PersionalFactor() {
14 } 15 }
15 16
16 - public PersionalFactor(List<Integer> brandIds, List<SortPriceArea> sortPriceAreas) { 17 + public PersionalFactor(List<Integer> brandIds, List<SortPriceArea> sortPriceAreas,String userFactor){
17 this.brandIds = brandIds; 18 this.brandIds = brandIds;
18 this.sortPriceAreas = sortPriceAreas; 19 this.sortPriceAreas = sortPriceAreas;
  20 + this.userFactor = userFactor;
19 } 21 }
20 22
21 public void setBrandIds(List<Integer> brandIds) { 23 public void setBrandIds(List<Integer> brandIds) {
@@ -34,6 +36,14 @@ public class PersionalFactor implements Serializable{ @@ -34,6 +36,14 @@ public class PersionalFactor implements Serializable{
34 return sortPriceAreas; 36 return sortPriceAreas;
35 } 37 }
36 38
  39 + public String getUserFactor() {
  40 + return userFactor;
  41 + }
  42 +
  43 + public void setUserFactor(String userFactor) {
  44 + this.userFactor = userFactor;
  45 + }
  46 +
37 public static class SortPriceArea implements Serializable{ 47 public static class SortPriceArea implements Serializable{
38 48
39 private static final long serialVersionUID = -7973209074997705083L; 49 private static final long serialVersionUID = -7973209074997705083L;
@@ -71,7 +71,7 @@ class PersionalFactorPageComponent { @@ -71,7 +71,7 @@ class PersionalFactorPageComponent {
71 Map<String, Aggregation> aggregationMap = searchResult.getAggMaps(); 71 Map<String, Aggregation> aggregationMap = searchResult.getAggMaps();
72 List<Integer> brandIds = this.getBrandIdsFromAggregationMap(aggregationMap); 72 List<Integer> brandIds = this.getBrandIdsFromAggregationMap(aggregationMap);
73 List<PersionalFactor.SortPriceArea> sortPriceAreas = this.getSortPriceAreasFromAggregationMap(aggregationMap); 73 List<PersionalFactor.SortPriceArea> sortPriceAreas = this.getSortPriceAreasFromAggregationMap(aggregationMap);
74 - pagePersionalFactor = new PersionalFactor(brandIds, sortPriceAreas); 74 + pagePersionalFactor = new PersionalFactor(brandIds, sortPriceAreas,null);
75 //6、加入缓存 75 //6、加入缓存
76 searchCacheService.addSerializableObjectToCache(searchCacheFactory.getAggregationSearchCache(),cacheKey,pagePersionalFactor,true); 76 searchCacheService.addSerializableObjectToCache(searchCacheFactory.getAggregationSearchCache(),cacheKey,pagePersionalFactor,true);
77 return pagePersionalFactor; 77 return pagePersionalFactor;
@@ -24,7 +24,8 @@ class PersionalFactorUserComponent { @@ -24,7 +24,8 @@ class PersionalFactorUserComponent {
24 for (int i = 0; i < 50; i++) { 24 for (int i = 0; i < 50; i++) {
25 sortPriceArea.add(new PersionalFactor.SortPriceArea((int) (Math.random() * 1000), (int) (Math.random() * 3))); 25 sortPriceArea.add(new PersionalFactor.SortPriceArea((int) (Math.random() * 1000), (int) (Math.random() * 3)));
26 } 26 }
27 - return new PersionalFactor(brandIds, sortPriceArea); 27 + String factor = "";
  28 + return new PersionalFactor(brandIds, sortPriceArea,factor);
28 } 29 }
29 30
30 31
1 package com.yoho.search.recall.scene.persional; 1 package com.yoho.search.recall.scene.persional;
2 2
3 import com.yoho.search.recall.scene.models.ParamQueryFilter; 3 import com.yoho.search.recall.scene.models.ParamQueryFilter;
  4 +import com.yoho.search.recall.scene.models.RecallParams;
4 import org.slf4j.Logger; 5 import org.slf4j.Logger;
5 import org.slf4j.LoggerFactory; 6 import org.slf4j.LoggerFactory;
6 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.beans.factory.annotation.Autowired;
@@ -22,20 +23,23 @@ public class RecallPersionalService { @@ -22,20 +23,23 @@ public class RecallPersionalService {
22 /** 23 /**
23 * 获取个性化因子 24 * 获取个性化因子
24 * 25 *
25 - * @param paramQueryFilter  
26 - * @param udid 26 + * @param recallParams
27 * @return 27 * @return
28 */ 28 */
29 - public PersionalFactor queryPersionalFactor(ParamQueryFilter paramQueryFilter, int uid, String udid) {  
30 - //1、获取页面上的个性化因子  
31 - PersionalFactor pageFactor = pageComponent.queryPagePersionalFactor(paramQueryFilter);  
32 - //2、获取用户的个性化因子  
33 - PersionalFactor userFactor = userComponent.queryUserPersionalFactor(uid, udid);  
34 - //3、join获取最终的结果  
35 - List<Integer> brandIds = this.innerJoin(pageFactor.getBrandIds(),userFactor.getBrandIds(),10);  
36 - List<PersionalFactor.SortPriceArea> sortPriceAreas = this.innerJoin(pageFactor.getSortPriceAreas(),userFactor.getSortPriceAreas(),5);  
37 - //logger.info("getPersionalUseFactor,brandIds is[{}],sortPriceAreas is [{}]",brandIds,sortPriceAreas);  
38 - return new PersionalFactor(brandIds, sortPriceAreas); 29 + public PersionalFactor queryPersionalFactor(RecallParams recallParams) {
  30 + try {
  31 + //1、获取页面上的个性化因子
  32 + PersionalFactor pageFactor = pageComponent.queryPagePersionalFactor(recallParams.getParamQueryFilter());
  33 + //2、获取用户的个性化因子
  34 + PersionalFactor userFactor = userComponent.queryUserPersionalFactor(recallParams.getUid(), recallParams.getUdid());
  35 + //3、join获取最终的结果
  36 + List<Integer> brandIds = this.innerJoin(pageFactor.getBrandIds(),userFactor.getBrandIds(),10);
  37 + List<PersionalFactor.SortPriceArea> sortPriceAreas = this.innerJoin(pageFactor.getSortPriceAreas(),userFactor.getSortPriceAreas(),5);
  38 + return new PersionalFactor(brandIds, sortPriceAreas,userFactor.getUserFactor());
  39 + }catch (Exception e){
  40 + logger.error(e.getMessage());
  41 + return new PersionalFactor(new ArrayList<>(),new ArrayList<>(),"");
  42 + }
39 } 43 }
40 44
41 private <T> List<T> innerJoin(List<T> aList,List<T> bList,int size) { 45 private <T> List<T> innerJoin(List<T> aList,List<T> bList,int size) {
1 package com.yoho.search.recall.sort; 1 package com.yoho.search.recall.sort;
2 2
3 -import java.util.ArrayList;  
4 -import java.util.Arrays;  
5 -import java.util.Collections;  
6 -import java.util.HashSet;  
7 -import java.util.Iterator;  
8 -import java.util.List;  
9 -import java.util.Map;  
10 -import java.util.Set;  
11 -  
12 -import com.yoho.search.service.helper.SearchCommonHelper;  
13 -import org.apache.commons.collections.MapUtils;  
14 -import org.apache.commons.lang.StringUtils;  
15 -import org.springframework.beans.factory.annotation.Autowired;  
16 -import org.springframework.stereotype.Service;  
17 -  
18 import com.alibaba.fastjson.JSONObject; 3 import com.alibaba.fastjson.JSONObject;
19 import com.yoho.search.base.models.RecallType; 4 import com.yoho.search.base.models.RecallType;
20 import com.yoho.search.base.utils.CollectionUtils; 5 import com.yoho.search.base.utils.CollectionUtils;
21 import com.yoho.search.base.utils.ProductIndexEsField; 6 import com.yoho.search.base.utils.ProductIndexEsField;
22 import com.yoho.search.common.cache.aop.SearchCacheAble; 7 import com.yoho.search.common.cache.aop.SearchCacheAble;
23 import com.yoho.search.models.SearchApiResult; 8 import com.yoho.search.models.SearchApiResult;
24 -import com.yoho.search.service.base.ProductListSortKey;  
25 -import com.yoho.search.service.base.ProductListSortService;  
26 import com.yoho.search.recall.sort.helper.RecallPersionalHelper; 9 import com.yoho.search.recall.sort.helper.RecallPersionalHelper;
27 import com.yoho.search.recall.sort.helper.RecallServiceHelper; 10 import com.yoho.search.recall.sort.helper.RecallServiceHelper;
28 -import com.yoho.search.recall.sort.model.RecallProductInfoList;  
29 -import com.yoho.search.recall.sort.model.RecallProductSknList;  
30 -import com.yoho.search.recall.sort.model.RecallResult;  
31 -import com.yoho.search.recall.sort.model.RecallSearchResult;  
32 -import com.yoho.search.recall.sort.model.UserLikeBrands;  
33 -import com.yoho.search.recall.sort.strategy.AddFlowStrategy;  
34 -import com.yoho.search.recall.sort.strategy.CommonStrategy;  
35 -import com.yoho.search.recall.sort.strategy.DirectTrainStrategy;  
36 -import com.yoho.search.recall.sort.strategy.FirstProductSknStrategy;  
37 -import com.yoho.search.recall.sort.strategy.IRecallStrategy;  
38 -import com.yoho.search.recall.sort.strategy.NewPromotionStrategy;  
39 -import com.yoho.search.recall.sort.strategy.NewReducePriceStrategy;  
40 -import com.yoho.search.recall.sort.strategy.NewShelveStrategy;  
41 -import com.yoho.search.recall.sort.strategy.NewShopStrategy;  
42 -import sun.applet.Main; 11 +import com.yoho.search.recall.sort.model.*;
  12 +import com.yoho.search.recall.sort.strategy.*;
  13 +import com.yoho.search.service.base.ProductListSortKey;
  14 +import com.yoho.search.service.base.ProductListSortService;
  15 +import com.yoho.search.service.helper.SearchCommonHelper;
  16 +import org.apache.commons.collections.MapUtils;
  17 +import org.apache.commons.lang.StringUtils;
  18 +import org.springframework.beans.factory.annotation.Autowired;
  19 +import org.springframework.stereotype.Service;
  20 +
  21 +import java.util.*;
43 22
44 @Service 23 @Service
45 public class SortRecallSceneService extends AbstractRecallService { 24 public class SortRecallSceneService extends AbstractRecallService {
@@ -164,9 +143,9 @@ public class SortRecallSceneService extends AbstractRecallService { @@ -164,9 +143,9 @@ public class SortRecallSceneService extends AbstractRecallService {
164 // 3、加入剩余商品 143 // 3、加入剩余商品
165 results.addAll(productList); 144 results.addAll(productList);
166 // 4、品牌打散 145 // 4、品牌打散
167 - ProductListSortKey productSortKey = new ProductListSortKey() { 146 + results = productListSortService.sortProductList(results, new ProductListSortKey<Map<String, Object>>() {
168 @Override 147 @Override
169 - public String getSortKey(Map<?, ?> product) { 148 + public String getSortKey(Map<String, Object> product) {
170 return MapUtils.getString(product, ProductIndexEsField.brandId, "0"); 149 return MapUtils.getString(product, ProductIndexEsField.brandId, "0");
171 } 150 }
172 151
@@ -174,8 +153,7 @@ public class SortRecallSceneService extends AbstractRecallService { @@ -174,8 +153,7 @@ public class SortRecallSceneService extends AbstractRecallService {
174 public int getMaxCount() { 153 public int getMaxCount() {
175 return 2; 154 return 2;
176 } 155 }
177 - };  
178 - results = productListSortService.sortProductMapList(results, productSortKey); 156 + });
179 // 5、回设productList 157 // 5、回设productList
180 recallResult.setProductList(results); 158 recallResult.setProductList(results);
181 return recallResult; 159 return recallResult;
  1 +package com.yoho.search.service.base;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.yoho.search.base.utils.ISearchConstants;
  5 +import com.yoho.search.core.es.model.SearchParam;
  6 +import com.yoho.search.core.es.model.SearchResult;
  7 +import com.yoho.search.service.base.index.ProductIndexBaseService;
  8 +import org.apache.commons.collections.MapUtils;
  9 +import org.springframework.beans.factory.annotation.Autowired;
  10 +import org.springframework.stereotype.Component;
  11 +
  12 +import java.util.List;
  13 +import java.util.Map;
  14 +
  15 +@Component
  16 +public class FillProductListService {
  17 +
  18 + @Autowired
  19 + private SearchCommonService searchCommonService;
  20 + @Autowired
  21 + private ProductIndexBaseService productIndexBaseService;
  22 + @Autowired
  23 + private ProductListSortService productListSortService;
  24 +
  25 + public JSONObject queryProductListResult(SearchParam searchParam){
  26 + // 1)设置返回的参数【节省带宽】
  27 + List<String> includeFields = productIndexBaseService.getProductIndexIncludeFields();
  28 + searchParam.setIncludeFields(includeFields);
  29 +
  30 + // 2)查询
  31 + SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
  32 + List<Map<String, Object>> product_list = productIndexBaseService.getProductListWithPricePlan(searchResult.getResultList());
  33 +
  34 + // 3)品牌品类打散
  35 + product_list = productListSortService.sortProductList(product_list, new ProductListSortKey<Map<String, Object>>() {
  36 + @Override
  37 + public String getSortKey(Map<String, Object> product) {
  38 + return MapUtils.getString(product, "brand_id", "0");
  39 + }
  40 + @Override
  41 + public int getMaxCount() {
  42 + return 2;
  43 + }
  44 + });
  45 +
  46 + // 4)构造返回结果
  47 + JSONObject dataMap = new JSONObject();
  48 + dataMap.put("total", searchResult.getTotal());
  49 + dataMap.put("page", searchResult.getPage());
  50 + dataMap.put("page_size", searchParam.getSize());
  51 + dataMap.put("page_total", searchResult.getTotalPage());
  52 + dataMap.put("product_list", product_list);
  53 + return dataMap;
  54 + }
  55 +
  56 +}