Authored by hugufei

优化通常场景的召回代码

1 package com.yoho.search.common.cache.aop; 1 package com.yoho.search.common.cache.aop;
2 2
  3 +
3 public abstract class SearchCacheAbleParam { 4 public abstract class SearchCacheAbleParam {
4 5
5 - public abstract String searchCacheKey(); 6 + public abstract String toCacheKeyValue();
6 7
7 } 8 }
@@ -85,7 +85,7 @@ public class SearchCacheAspect { @@ -85,7 +85,7 @@ public class SearchCacheAspect {
85 } 85 }
86 Object object = arges[0]; 86 Object object = arges[0];
87 if (object instanceof SearchCacheAbleParam) { 87 if (object instanceof SearchCacheAbleParam) {
88 - return ((SearchCacheAbleParam) object).searchCacheKey(); 88 + return this.getCacheKey((SearchCacheAbleParam) object, searchCacheAble);
89 } 89 }
90 if (object instanceof HttpServletRequest) { 90 if (object instanceof HttpServletRequest) {
91 return this.getCacheKey((HttpServletRequest) object, searchCacheAble); 91 return this.getCacheKey((HttpServletRequest) object, searchCacheAble);
@@ -96,12 +96,18 @@ public class SearchCacheAspect { @@ -96,12 +96,18 @@ public class SearchCacheAspect {
96 return null; 96 return null;
97 } 97 }
98 98
99 - // 获取请求的参数 99 + // 获取SearchCacheAbleParam的缓存key
  100 + private String getCacheKey(SearchCacheAbleParam searchCacheAbleParam, SearchCacheAble searchCacheAble) {
  101 + String valueString = searchCacheAbleParam.toCacheKeyValue();
  102 + return this.getRealCacheKey(valueString, searchCacheAble);
  103 + }
  104 +
  105 + // 获取httpServletRequest的缓存key
100 private String getCacheKey(HttpServletRequest httpServletRequest, SearchCacheAble searchCacheAble) { 106 private String getCacheKey(HttpServletRequest httpServletRequest, SearchCacheAble searchCacheAble) {
101 Map<String, String> paramMap = HttpServletRequestUtils.transParamType(httpServletRequest); 107 Map<String, String> paramMap = HttpServletRequestUtils.transParamType(httpServletRequest);
102 return this.getCacheKey(paramMap, searchCacheAble); 108 return this.getCacheKey(paramMap, searchCacheAble);
103 } 109 }
104 - 110 +
105 // 获取请求的参数 111 // 获取请求的参数
106 private String getCacheKey(Map<?, ?> paramMap, SearchCacheAble searchCacheAble) { 112 private String getCacheKey(Map<?, ?> paramMap, SearchCacheAble searchCacheAble) {
107 List<String> includeParams = Arrays.asList(searchCacheAble.includeParams()); 113 List<String> includeParams = Arrays.asList(searchCacheAble.includeParams());
@@ -114,9 +120,13 @@ public class SearchCacheAspect { @@ -114,9 +120,13 @@ public class SearchCacheAspect {
114 } else { 120 } else {
115 paramKey = HttpServletRequestUtils.genParamString(paramMap); 121 paramKey = HttpServletRequestUtils.genParamString(paramMap);
116 } 122 }
  123 + return this.getRealCacheKey(paramKey, searchCacheAble);
  124 + }
  125 +
  126 + private String getRealCacheKey(String value,SearchCacheAble searchCacheAble){
117 StringBuilder realCacheKey = new StringBuilder("YOHOSEARCH:"); 127 StringBuilder realCacheKey = new StringBuilder("YOHOSEARCH:");
118 - realCacheKey.append(searchCacheAble.cacheName());  
119 - realCacheKey.append(MD5Util.string2MD5(paramKey)); 128 + realCacheKey.append(searchCacheAble.cacheName()).append(":");
  129 + realCacheKey.append(MD5Util.string2MD5(value));
120 return realCacheKey.toString(); 130 return realCacheKey.toString();
121 } 131 }
122 132
@@ -137,11 +137,11 @@ public class CommonSceneProductListService { @@ -137,11 +137,11 @@ public class CommonSceneProductListService {
137 results.put("product_list", this.getProductListFromCache(productInfoMapResult, commonRecallResult, page, viewNum)); 137 results.put("product_list", this.getProductListFromCache(productInfoMapResult, commonRecallResult, page, viewNum));
138 } else { 138 } else {
139 // 8、其他页码使用CommonRecallParamService去查询 139 // 8、其他页码使用CommonRecallParamService去查询
140 - results.put("product_list", this.queryProductListForOtherPageIndex(paramMap, commonRecallResult, page - recallMaxPage)); 140 + results.put("product_list", this.queryProductListForOtherPageIndex(paramMap, commonRecallResult, page - recallMaxPage, viewNum));
141 } 141 }
142 return new SearchApiResult().setData(results); 142 return new SearchApiResult().setData(results);
143 } 143 }
144 - 144 +
145 /** 145 /**
146 * 其他页码的处理方式 146 * 其他页码的处理方式
147 * 147 *
@@ -150,22 +150,19 @@ public class CommonSceneProductListService { @@ -150,22 +150,19 @@ public class CommonSceneProductListService {
150 * @param realPage 150 * @param realPage
151 * @return 151 * @return
152 */ 152 */
153 - private SearchApiResult queryProductListForOtherPageIndex(Map<String, String> paramMap, CommonRecallResult commonRecallResult, int realPage) { 153 + private SearchApiResult queryProductListForOtherPageIndex(Map<String, String> paramMap, CommonRecallResult commonRecallResult, int realPage, int viewNum) {
154 // 1、其他页码使用CommonRecallParamService去查询 154 // 1、其他页码使用CommonRecallParamService去查询
155 - CommonRecallParam commonRecallParam = new CommonRecallParam(paramMap); 155 + CommonRecallParam commonRecallParam = new CommonRecallParam(paramMap, 0, realPage, viewNum);
156 // 2、前面几个已经召回的需要排除 156 // 2、前面几个已经召回的需要排除
157 BoolQueryBuilder extendMustFilter = QueryBuilders.boolQuery(); 157 BoolQueryBuilder extendMustFilter = QueryBuilders.boolQuery();
158 extendMustFilter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, commonRecallResult.toSknList())); 158 extendMustFilter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, commonRecallResult.toSknList()));
159 commonRecallParam.setExtendMustFilter(extendMustFilter); 159 commonRecallParam.setExtendMustFilter(extendMustFilter);
160 - // 3、设置真实的分页参数  
161 - commonRecallParam.setPage(realPage);  
162 - // 4、构造sort 160 + // 3、构造sort
163 List<SortBuilder<?>> sortBuilders = new ArrayList<SortBuilder<?>>(); 161 List<SortBuilder<?>> sortBuilders = new ArrayList<SortBuilder<?>>();
164 sortBuilders.add(SortBuilders.fieldSort(ProductIndexEsField.sevendayMoney).order(SortOrder.DESC)); 162 sortBuilders.add(SortBuilders.fieldSort(ProductIndexEsField.sevendayMoney).order(SortOrder.DESC));
165 commonRecallParam.setSortBuilders(sortBuilders); 163 commonRecallParam.setSortBuilders(sortBuilders);
166 - // 5、执行查询 164 + // 4、执行查询
167 return cacheAbleServiceHelper.queryProductListByRecallParam(commonRecallParam); 165 return cacheAbleServiceHelper.queryProductListByRecallParam(commonRecallParam);
168 -  
169 } 166 }
170 167
171 private long getTotalPage(long total, int viewNum) { 168 private long getTotalPage(long total, int viewNum) {
@@ -204,23 +201,19 @@ public class CommonSceneProductListService { @@ -204,23 +201,19 @@ public class CommonSceneProductListService {
204 */ 201 */
205 private CommonRecallResult callUserScoreAndRank(Map<String, String> paramMap, CommonRecallResult commonRecallResult) { 202 private CommonRecallResult callUserScoreAndRank(Map<String, String> paramMap, CommonRecallResult commonRecallResult) {
206 PersonalizedSearch personalizedSearch = personalVectorFeatureSearch.getPersonalizedSearch(paramMap); 203 PersonalizedSearch personalizedSearch = personalVectorFeatureSearch.getPersonalizedSearch(paramMap);
207 - if (personalizedSearch == null) {  
208 - Collections.shuffle(commonRecallResult.getRecallSknList());  
209 - return commonRecallResult;  
210 - }  
211 - String userVectorFeature = personalizedSearch.getUserVectorFeature();  
212 - String[] userFeatureFactorArr = userVectorFeature.split(",");  
213 - String vectorFeatureVersion = personalizedSearch.getVectorFeatureVersion(); 204 + UserFeatureFactor userFeatureFactor = new UserFeatureFactor(personalizedSearch);
214 List<String> firstProductSkns = Arrays.asList(MapUtils.getString(paramMap, SearchRequestParams.PARAM_SEARCH_FIRST_PRODUCRSKN, "").split(",")); 205 List<String> firstProductSkns = Arrays.asList(MapUtils.getString(paramMap, SearchRequestParams.PARAM_SEARCH_FIRST_PRODUCRSKN, "").split(","));
215 for (CommonRecallSkn commonRecallSkn : commonRecallResult.getRecallSknList()) { 206 for (CommonRecallSkn commonRecallSkn : commonRecallResult.getRecallSknList()) {
216 if (firstProductSkns.contains(String.valueOf(commonRecallSkn.getProductSkn()))) { 207 if (firstProductSkns.contains(String.valueOf(commonRecallSkn.getProductSkn()))) {
217 - commonRecallSkn.setScore(10000); 208 + commonRecallSkn.setScore(10000);// firstSkn排第一个
218 } else { 209 } else {
219 - commonRecallSkn.setScore(productFeatureFactorHepler.calProductFeatureFactor(userFeatureFactorArr, vectorFeatureVersion, commonRecallSkn.getProductFeatureFactor())); 210 + commonRecallSkn.setScore(productFeatureFactorHepler.calProductFeatureFactor(userFeatureFactor, commonRecallSkn.getProductFeatureFactor()));
220 } 211 }
221 } 212 }
222 Collections.sort(commonRecallResult.getRecallSknList()); 213 Collections.sort(commonRecallResult.getRecallSknList());
  214 + for (CommonRecallSkn commonRecallSkn : commonRecallResult.getRecallSknList()) {
  215 + System.out.println(commonRecallSkn.score());
  216 + }
223 return commonRecallResult; 217 return commonRecallResult;
224 } 218 }
225 -  
226 } 219 }
1 package com.yoho.search.service.recall; 1 package com.yoho.search.service.recall;
2 2
  3 +import org.apache.commons.lang.StringUtils;
  4 +import org.slf4j.Logger;
  5 +import org.slf4j.LoggerFactory;
3 import org.springframework.stereotype.Component; 6 import org.springframework.stereotype.Component;
4 7
  8 +import com.yoho.search.core.personalized.PersonalizedSearch;
  9 +
5 @Component 10 @Component
6 public class ProductFeatureFactorHepler { 11 public class ProductFeatureFactorHepler {
  12 +
  13 + private static final Logger logger = LoggerFactory.getLogger(ProductFeatureFactorHepler.class);
7 14
8 - private static double baseConstant = 1;  
9 - private static double factorConstant = 1; 15 + private static double baseConstant = 10;
  16 + private static double factorConstant = 10;
10 17
11 - public double calProductFeatureFactor(String[] userFeatureFactorArr,String vectorFeatureVersion,String productFeatureFactor){  
12 - if(userFeatureFactorArr==null || userFeatureFactorArr.length==0){  
13 - return baseConstant; 18 + public double calProductFeatureFactor(UserFeatureFactor userFeatureFactor,String productFeatureFactor){
  19 + try {
  20 + //用户向量不存在,则直接随机
  21 + if(userFeatureFactor==null || StringUtils.isBlank(userFeatureFactor.vectorFeatureVersion)){
  22 + return baseConstant * Math.random();//随机数
  23 + }
  24 + if(StringUtils.isBlank(productFeatureFactor)){
  25 + return baseConstant;
  26 + }
  27 + String versionPrefix = userFeatureFactor.vectorFeatureVersion + "|";
  28 + if (!productFeatureFactor.trim().startsWith(versionPrefix)) {
  29 + return baseConstant;
  30 + }
  31 + String[] productFeatureFactorArr = productFeatureFactor.trim().substring(versionPrefix.length()).split(",");
  32 + if (productFeatureFactorArr == null || productFeatureFactorArr.length != userFeatureFactor.dimensionOfFactors) {
  33 + return baseConstant;//随机数
  34 + }
  35 + double prodFeatureVectorNorm = 0.0D;
  36 + double productiveSum = 0.0D;
  37 + double tempProdFactor;
  38 + for (int i = 0; i < userFeatureFactor.dimensionOfFactors; i++) {
  39 + tempProdFactor = Double.parseDouble(productFeatureFactorArr[i].trim());
  40 + productiveSum += tempProdFactor * userFeatureFactor.userFeatureFactors[i];
  41 + prodFeatureVectorNorm += tempProdFactor * tempProdFactor;
  42 + }
  43 + if (prodFeatureVectorNorm == 0) {
  44 + return baseConstant;
  45 + }
  46 + double cosScore = productiveSum / (Math.sqrt(prodFeatureVectorNorm) * Math.sqrt(userFeatureFactor.userFeatureVectorNorm));
  47 + double finalScore = baseConstant + factorConstant * cosScore;
  48 + return finalScore;
  49 + } catch (Exception e) {
  50 + logger.error(e.getMessage(),e);
  51 + return factorConstant * Math.random();//随机数
14 } 52 }
15 - int dimensionOfFactors = userFeatureFactorArr.length;  
16 - double[] userFeatureFactors = new double[dimensionOfFactors];  
17 - double temp;  
18 - double userFeatureVectorNorm = 0.0D;  
19 - for (int index = 0; index < dimensionOfFactors; index++) {  
20 - temp = Double.parseDouble(userFeatureFactorArr[index].trim());  
21 - userFeatureFactors[index] = temp;  
22 - userFeatureVectorNorm += temp * temp;  
23 - }  
24 - String versionPrefix = vectorFeatureVersion + "|";  
25 - if (!productFeatureFactor.trim().startsWith(versionPrefix)) {  
26 - return baseConstant;  
27 - }  
28 - String[] productFeatureFactorArr = productFeatureFactor.trim().substring(versionPrefix.length()).split(",");  
29 - if (productFeatureFactorArr == null || productFeatureFactorArr.length != userFeatureFactors.length) {  
30 - return baseConstant;  
31 - }  
32 - double prodFeatureVectorNorm = 0.0D;  
33 - double productiveSum = 0.0D;  
34 - double tempProdFactor;  
35 - for (int i = 0; i < dimensionOfFactors; i++) {  
36 - tempProdFactor = Double.parseDouble(productFeatureFactorArr[i].trim());  
37 - productiveSum += tempProdFactor * userFeatureFactors[i];  
38 - prodFeatureVectorNorm += tempProdFactor * tempProdFactor;  
39 - }  
40 - if (prodFeatureVectorNorm == 0) {  
41 - return baseConstant;  
42 - }  
43 - double cosScore = productiveSum / (Math.sqrt(prodFeatureVectorNorm) * Math.sqrt(userFeatureVectorNorm));  
44 - double finalScore = baseConstant + factorConstant * cosScore;  
45 - return finalScore;  
46 } 53 }
  54 +
  55 + public static void main(String[] args) {
  56 + PersonalizedSearch personalizedSearch = new PersonalizedSearch("0","20171018","-0.43475,0.286214,0.378061,0.836893,0.023244,0.568391,0.557073,-0.693003,0.03146,-0.4763,-0.261971,-0.727929,0.208787,0.637666,0.122361,-0.170466,-0.100151,-0.116521,-0.64368,1.365271,0.033476,-0.214706,0.146333,0.286707,-0.342803,0.347786,-0.36866,0.221598,0.671105,-0.100859,0.089867,-0.380323,-0.071117,-0.766423,-0.239785,0.311385,-0.632959,0.112586,0.535046,0.081164,0.493848,0.165094,0.0257,-0.031391,-0.929653,0.064834,-0.834791,0.046314,-0.478439,0.097075,-0.640102,0.091841,2.75E-4,-0.132861,0.052851,0.021564,0.170549,0.984287,-0.02477,-0.593686,0.180803,-0.122516,0.120295,-0.387301,0.511272,-0.398194,0.734716,-0.193353,-0.252243,-0.867587,-0.505197,0.092014,0.906497,-0.372965,0.039183,0.292307,0.314153,-0.051735,-0.194966,0.667724,-0.176847,0.472125,-0.812535,0.712065,0.229543,-0.35451,0.580328,0.051884,0.841284,0.19402,1.140726,-0.217064,-1.401154,0.240292,0.134513,0.490654,0.423197,-0.536384,-0.335227,0.19993");
  57 + UserFeatureFactor userFeatureFactor = new UserFeatureFactor(personalizedSearch);
  58 + System.out.println(new ProductFeatureFactorHepler().calProductFeatureFactor(userFeatureFactor, "20171018|-0.43175,0.286214,0.378061,0.836893,0.023244,0.568391,0.557073,-0.693003,0.03146,-0.4763,-0.261971,-0.727929,0.208787,0.637666,0.122361,-0.170466,-0.100151,-0.116521,-0.64368,1.365271,0.033476,-0.214706,0.146333,0.286707,-0.342803,0.347786,-0.36866,0.221598,0.671105,-0.100859,0.089867,-0.380323,-0.071117,-0.766423,-0.239785,0.311385,-0.632959,0.112586,0.535046,0.081164,0.493848,0.165094,0.0257,-0.031391,-0.929653,0.064834,-0.834791,0.046314,-0.478439,0.097075,-0.640102,0.091841,2.75E-4,-0.132861,0.052851,0.021564,0.170549,0.984287,-0.02477,-0.593686,0.180803,-0.122516,0.120295,-0.387301,0.511272,-0.398194,0.734716,-0.193353,-0.252243,-0.867587,-0.505197,0.092014,0.906497,-0.372965,0.039183,0.292307,0.314153,-0.051735,-0.194966,0.667724,-0.176847,0.472125,-0.812535,0.712065,0.229543,-0.35451,0.580328,0.051884,0.841284,0.19402,1.140726,-0.217064,-1.401154,0.240292,0.134513,0.490654,0.423197,-0.536384,-0.335227,0.19993"));
  59 + }
  60 +
47 } 61 }
  1 +package com.yoho.search.service.recall;
  2 +
  3 +import com.yoho.search.core.personalized.PersonalizedSearch;
  4 +
  5 +public class UserFeatureFactor {
  6 +
  7 + public int dimensionOfFactors = 0;
  8 + public double[] userFeatureFactors = null;
  9 + public String vectorFeatureVersion;
  10 + public double userFeatureVectorNorm = 0.0D;
  11 +
  12 + public UserFeatureFactor(PersonalizedSearch personalizedSearch) {
  13 + if (personalizedSearch == null) {
  14 + return;
  15 + }
  16 + this.vectorFeatureVersion = personalizedSearch.getVectorFeatureVersion();
  17 +
  18 + String userVectorFeature = personalizedSearch.getUserVectorFeature();
  19 + String[] userFeatureFactorArr = userVectorFeature.split(",");
  20 + dimensionOfFactors = userFeatureFactorArr.length;
  21 + userFeatureFactors = new double[dimensionOfFactors];
  22 + double temp;
  23 + for (int index = 0; index < dimensionOfFactors; index++) {
  24 + temp = Double.parseDouble(userFeatureFactorArr[index].trim());
  25 + userFeatureFactors[index] = temp;
  26 + userFeatureVectorNorm += temp * temp;
  27 + }
  28 + }
  29 +
  30 +
  31 +}
@@ -86,7 +86,7 @@ public class CacheAbleServiceHelper { @@ -86,7 +86,7 @@ public class CacheAbleServiceHelper {
86 * @param paramMap 86 * @param paramMap
87 * @return 87 * @return
88 */ 88 */
89 - @SearchCacheAble(cacheName = "COMMON_SCENE_QUERY_BY_PARAM", cacheInMinute = 10, excludeParams = { "uid" }) 89 + @SearchCacheAble(cacheName = "COMMON_SCENE_QUERY_BY_PARAM", cacheInMinute = 10)
90 public SearchApiResult queryProductListByRecallParam(CommonRecallParam commonRecallParam) { 90 public SearchApiResult queryProductListByRecallParam(CommonRecallParam commonRecallParam) {
91 try { 91 try {
92 // 1、获取参数 92 // 1、获取参数
1 package com.yoho.search.service.recall.model; 1 package com.yoho.search.service.recall.model;
2 2
3 import java.util.ArrayList; 3 import java.util.ArrayList;
  4 +import java.util.Arrays;
4 import java.util.List; 5 import java.util.List;
5 import java.util.Map; 6 import java.util.Map;
6 7
@@ -20,11 +21,15 @@ public class CommonRecallParam extends SearchCacheAbleParam { @@ -20,11 +21,15 @@ public class CommonRecallParam extends SearchCacheAbleParam {
20 private Map<String, String> paramMap; 21 private Map<String, String> paramMap;
21 private BoolQueryBuilder extendMustFilter; 22 private BoolQueryBuilder extendMustFilter;
22 private List<SortBuilder<?>> sortBuilders = new ArrayList<SortBuilder<?>>(); 23 private List<SortBuilder<?>> sortBuilders = new ArrayList<SortBuilder<?>>();
  24 + private int uid;
23 private int page; 25 private int page;
24 private int viewNum; 26 private int viewNum;
25 27
26 - public CommonRecallParam(Map<String, String> paramMap){ 28 + public CommonRecallParam(Map<String, String> paramMap,int uid,int page,int viewNum){
27 this.paramMap = paramMap; 29 this.paramMap = paramMap;
  30 + this.uid = uid;
  31 + this.page = page;
  32 + this.viewNum = viewNum;
28 } 33 }
29 34
30 public Map<String, String> getParamMap() { 35 public Map<String, String> getParamMap() {
@@ -47,36 +52,26 @@ public class CommonRecallParam extends SearchCacheAbleParam { @@ -47,36 +52,26 @@ public class CommonRecallParam extends SearchCacheAbleParam {
47 this.sortBuilders = sortBuilders; 52 this.sortBuilders = sortBuilders;
48 } 53 }
49 54
50 - public int getPage() {  
51 - return page; 55 + public int getUid() {
  56 + return uid;
52 } 57 }
53 58
54 - public void setPage(int page) {  
55 - this.page = page; 59 + public int getPage() {
  60 + return page;
56 } 61 }
57 62
58 public int getViewNum() { 63 public int getViewNum() {
59 return viewNum; 64 return viewNum;
60 } 65 }
61 -  
62 - public void setViewNum(int viewNum) {  
63 - this.viewNum = viewNum;  
64 - }  
65 - 66 +
66 @Override 67 @Override
67 - public String searchCacheKey() { 68 + public String toCacheKeyValue() {
68 StringBuilder sb = new StringBuilder(); 69 StringBuilder sb = new StringBuilder();
69 - List<String> excludeParams = new ArrayList<String>();  
70 - excludeParams.add("uid");  
71 - if (page > 0) {  
72 - excludeParams.add("page");  
73 - }  
74 - if (viewNum > 0) {  
75 - excludeParams.add("viewNum");  
76 - } 70 + List<String> excludeParams = Arrays.asList("uid","page","viewNum");
77 sb.append("paramMap=").append(HttpServletRequestUtils.genParamStringWithExcludeParams(paramMap,excludeParams)); 71 sb.append("paramMap=").append(HttpServletRequestUtils.genParamStringWithExcludeParams(paramMap,excludeParams));
78 sb.append("&extendMustFilter=").append(extendMustFilter==null?"":extendMustFilter.toString()); 72 sb.append("&extendMustFilter=").append(extendMustFilter==null?"":extendMustFilter.toString());
79 sb.append("&sortBuilders=").append(sortBuilders==null||sortBuilders.isEmpty()?"":sortBuilders.toString()); 73 sb.append("&sortBuilders=").append(sortBuilders==null||sortBuilders.isEmpty()?"":sortBuilders.toString());
  74 + sb.append("&uid=").append(uid);
80 sb.append("&page=").append(page); 75 sb.append("&page=").append(page);
81 sb.append("&viewNum=").append(viewNum); 76 sb.append("&viewNum=").append(viewNum);
82 return sb.toString(); 77 return sb.toString();
@@ -2,6 +2,7 @@ package com.yoho.search.service.recall.model; @@ -2,6 +2,7 @@ package com.yoho.search.service.recall.model;
2 2
3 import java.io.Serializable; 3 import java.io.Serializable;
4 import java.util.ArrayList; 4 import java.util.ArrayList;
  5 +import java.util.Collections;
5 import java.util.List; 6 import java.util.List;
6 7
7 import org.apache.commons.lang.StringUtils; 8 import org.apache.commons.lang.StringUtils;
@@ -39,11 +40,12 @@ public class CommonRecallResult extends SearchCacheAbleParam implements Serializ @@ -39,11 +40,12 @@ public class CommonRecallResult extends SearchCacheAbleParam implements Serializ
39 for (CommonRecallSkn commonRecallSkn : recallSknList) { 40 for (CommonRecallSkn commonRecallSkn : recallSknList) {
40 productSkns.add(commonRecallSkn.getProductSkn()); 41 productSkns.add(commonRecallSkn.getProductSkn());
41 } 42 }
  43 + Collections.sort(productSkns);
42 return productSkns; 44 return productSkns;
43 } 45 }
44 46
45 @Override 47 @Override
46 - public String searchCacheKey() { 48 + public String toCacheKeyValue() {
47 return StringUtils.join(toSknList(),","); 49 return StringUtils.join(toSknList(),",");
48 } 50 }
49 51