Authored by hugufei

优化通常场景的召回代码

package com.yoho.search.common.cache.aop;
public abstract class SearchCacheAbleParam {
public abstract String searchCacheKey();
public abstract String toCacheKeyValue();
}
... ...
... ... @@ -85,7 +85,7 @@ public class SearchCacheAspect {
}
Object object = arges[0];
if (object instanceof SearchCacheAbleParam) {
return ((SearchCacheAbleParam) object).searchCacheKey();
return this.getCacheKey((SearchCacheAbleParam) object, searchCacheAble);
}
if (object instanceof HttpServletRequest) {
return this.getCacheKey((HttpServletRequest) object, searchCacheAble);
... ... @@ -96,12 +96,18 @@ public class SearchCacheAspect {
return null;
}
// 获取请求的参数
// 获取SearchCacheAbleParam的缓存key
private String getCacheKey(SearchCacheAbleParam searchCacheAbleParam, SearchCacheAble searchCacheAble) {
String valueString = searchCacheAbleParam.toCacheKeyValue();
return this.getRealCacheKey(valueString, searchCacheAble);
}
// 获取httpServletRequest的缓存key
private String getCacheKey(HttpServletRequest httpServletRequest, SearchCacheAble searchCacheAble) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(httpServletRequest);
return this.getCacheKey(paramMap, searchCacheAble);
}
// 获取请求的参数
private String getCacheKey(Map<?, ?> paramMap, SearchCacheAble searchCacheAble) {
List<String> includeParams = Arrays.asList(searchCacheAble.includeParams());
... ... @@ -114,9 +120,13 @@ public class SearchCacheAspect {
} else {
paramKey = HttpServletRequestUtils.genParamString(paramMap);
}
return this.getRealCacheKey(paramKey, searchCacheAble);
}
private String getRealCacheKey(String value,SearchCacheAble searchCacheAble){
StringBuilder realCacheKey = new StringBuilder("YOHOSEARCH:");
realCacheKey.append(searchCacheAble.cacheName());
realCacheKey.append(MD5Util.string2MD5(paramKey));
realCacheKey.append(searchCacheAble.cacheName()).append(":");
realCacheKey.append(MD5Util.string2MD5(value));
return realCacheKey.toString();
}
... ...
... ... @@ -137,11 +137,11 @@ public class CommonSceneProductListService {
results.put("product_list", this.getProductListFromCache(productInfoMapResult, commonRecallResult, page, viewNum));
} else {
// 8、其他页码使用CommonRecallParamService去查询
results.put("product_list", this.queryProductListForOtherPageIndex(paramMap, commonRecallResult, page - recallMaxPage));
results.put("product_list", this.queryProductListForOtherPageIndex(paramMap, commonRecallResult, page - recallMaxPage, viewNum));
}
return new SearchApiResult().setData(results);
}
/**
* 其他页码的处理方式
*
... ... @@ -150,22 +150,19 @@ public class CommonSceneProductListService {
* @param realPage
* @return
*/
private SearchApiResult queryProductListForOtherPageIndex(Map<String, String> paramMap, CommonRecallResult commonRecallResult, int realPage) {
private SearchApiResult queryProductListForOtherPageIndex(Map<String, String> paramMap, CommonRecallResult commonRecallResult, int realPage, int viewNum) {
// 1、其他页码使用CommonRecallParamService去查询
CommonRecallParam commonRecallParam = new CommonRecallParam(paramMap);
CommonRecallParam commonRecallParam = new CommonRecallParam(paramMap, 0, realPage, viewNum);
// 2、前面几个已经召回的需要排除
BoolQueryBuilder extendMustFilter = QueryBuilders.boolQuery();
extendMustFilter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, commonRecallResult.toSknList()));
commonRecallParam.setExtendMustFilter(extendMustFilter);
// 3、设置真实的分页参数
commonRecallParam.setPage(realPage);
// 4、构造sort
// 3、构造sort
List<SortBuilder<?>> sortBuilders = new ArrayList<SortBuilder<?>>();
sortBuilders.add(SortBuilders.fieldSort(ProductIndexEsField.sevendayMoney).order(SortOrder.DESC));
commonRecallParam.setSortBuilders(sortBuilders);
// 5、执行查询
// 4、执行查询
return cacheAbleServiceHelper.queryProductListByRecallParam(commonRecallParam);
}
private long getTotalPage(long total, int viewNum) {
... ... @@ -204,23 +201,19 @@ public class CommonSceneProductListService {
*/
private CommonRecallResult callUserScoreAndRank(Map<String, String> paramMap, CommonRecallResult commonRecallResult) {
PersonalizedSearch personalizedSearch = personalVectorFeatureSearch.getPersonalizedSearch(paramMap);
if (personalizedSearch == null) {
Collections.shuffle(commonRecallResult.getRecallSknList());
return commonRecallResult;
}
String userVectorFeature = personalizedSearch.getUserVectorFeature();
String[] userFeatureFactorArr = userVectorFeature.split(",");
String vectorFeatureVersion = personalizedSearch.getVectorFeatureVersion();
UserFeatureFactor userFeatureFactor = new UserFeatureFactor(personalizedSearch);
List<String> firstProductSkns = Arrays.asList(MapUtils.getString(paramMap, SearchRequestParams.PARAM_SEARCH_FIRST_PRODUCRSKN, "").split(","));
for (CommonRecallSkn commonRecallSkn : commonRecallResult.getRecallSknList()) {
if (firstProductSkns.contains(String.valueOf(commonRecallSkn.getProductSkn()))) {
commonRecallSkn.setScore(10000);
commonRecallSkn.setScore(10000);// firstSkn排第一个
} else {
commonRecallSkn.setScore(productFeatureFactorHepler.calProductFeatureFactor(userFeatureFactorArr, vectorFeatureVersion, commonRecallSkn.getProductFeatureFactor()));
commonRecallSkn.setScore(productFeatureFactorHepler.calProductFeatureFactor(userFeatureFactor, commonRecallSkn.getProductFeatureFactor()));
}
}
Collections.sort(commonRecallResult.getRecallSknList());
for (CommonRecallSkn commonRecallSkn : commonRecallResult.getRecallSknList()) {
System.out.println(commonRecallSkn.score());
}
return commonRecallResult;
}
}
... ...
package com.yoho.search.service.recall;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.yoho.search.core.personalized.PersonalizedSearch;
@Component
public class ProductFeatureFactorHepler {
private static final Logger logger = LoggerFactory.getLogger(ProductFeatureFactorHepler.class);
private static double baseConstant = 1;
private static double factorConstant = 1;
private static double baseConstant = 10;
private static double factorConstant = 10;
public double calProductFeatureFactor(String[] userFeatureFactorArr,String vectorFeatureVersion,String productFeatureFactor){
if(userFeatureFactorArr==null || userFeatureFactorArr.length==0){
return baseConstant;
public double calProductFeatureFactor(UserFeatureFactor userFeatureFactor,String productFeatureFactor){
try {
//用户向量不存在,则直接随机
if(userFeatureFactor==null || StringUtils.isBlank(userFeatureFactor.vectorFeatureVersion)){
return baseConstant * Math.random();//随机数
}
if(StringUtils.isBlank(productFeatureFactor)){
return baseConstant;
}
String versionPrefix = userFeatureFactor.vectorFeatureVersion + "|";
if (!productFeatureFactor.trim().startsWith(versionPrefix)) {
return baseConstant;
}
String[] productFeatureFactorArr = productFeatureFactor.trim().substring(versionPrefix.length()).split(",");
if (productFeatureFactorArr == null || productFeatureFactorArr.length != userFeatureFactor.dimensionOfFactors) {
return baseConstant;//随机数
}
double prodFeatureVectorNorm = 0.0D;
double productiveSum = 0.0D;
double tempProdFactor;
for (int i = 0; i < userFeatureFactor.dimensionOfFactors; i++) {
tempProdFactor = Double.parseDouble(productFeatureFactorArr[i].trim());
productiveSum += tempProdFactor * userFeatureFactor.userFeatureFactors[i];
prodFeatureVectorNorm += tempProdFactor * tempProdFactor;
}
if (prodFeatureVectorNorm == 0) {
return baseConstant;
}
double cosScore = productiveSum / (Math.sqrt(prodFeatureVectorNorm) * Math.sqrt(userFeatureFactor.userFeatureVectorNorm));
double finalScore = baseConstant + factorConstant * cosScore;
return finalScore;
} catch (Exception e) {
logger.error(e.getMessage(),e);
return factorConstant * Math.random();//随机数
}
int dimensionOfFactors = userFeatureFactorArr.length;
double[] userFeatureFactors = new double[dimensionOfFactors];
double temp;
double userFeatureVectorNorm = 0.0D;
for (int index = 0; index < dimensionOfFactors; index++) {
temp = Double.parseDouble(userFeatureFactorArr[index].trim());
userFeatureFactors[index] = temp;
userFeatureVectorNorm += temp * temp;
}
String versionPrefix = vectorFeatureVersion + "|";
if (!productFeatureFactor.trim().startsWith(versionPrefix)) {
return baseConstant;
}
String[] productFeatureFactorArr = productFeatureFactor.trim().substring(versionPrefix.length()).split(",");
if (productFeatureFactorArr == null || productFeatureFactorArr.length != userFeatureFactors.length) {
return baseConstant;
}
double prodFeatureVectorNorm = 0.0D;
double productiveSum = 0.0D;
double tempProdFactor;
for (int i = 0; i < dimensionOfFactors; i++) {
tempProdFactor = Double.parseDouble(productFeatureFactorArr[i].trim());
productiveSum += tempProdFactor * userFeatureFactors[i];
prodFeatureVectorNorm += tempProdFactor * tempProdFactor;
}
if (prodFeatureVectorNorm == 0) {
return baseConstant;
}
double cosScore = productiveSum / (Math.sqrt(prodFeatureVectorNorm) * Math.sqrt(userFeatureVectorNorm));
double finalScore = baseConstant + factorConstant * cosScore;
return finalScore;
}
public static void main(String[] args) {
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");
UserFeatureFactor userFeatureFactor = new UserFeatureFactor(personalizedSearch);
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"));
}
}
... ...
package com.yoho.search.service.recall;
import com.yoho.search.core.personalized.PersonalizedSearch;
public class UserFeatureFactor {
public int dimensionOfFactors = 0;
public double[] userFeatureFactors = null;
public String vectorFeatureVersion;
public double userFeatureVectorNorm = 0.0D;
public UserFeatureFactor(PersonalizedSearch personalizedSearch) {
if (personalizedSearch == null) {
return;
}
this.vectorFeatureVersion = personalizedSearch.getVectorFeatureVersion();
String userVectorFeature = personalizedSearch.getUserVectorFeature();
String[] userFeatureFactorArr = userVectorFeature.split(",");
dimensionOfFactors = userFeatureFactorArr.length;
userFeatureFactors = new double[dimensionOfFactors];
double temp;
for (int index = 0; index < dimensionOfFactors; index++) {
temp = Double.parseDouble(userFeatureFactorArr[index].trim());
userFeatureFactors[index] = temp;
userFeatureVectorNorm += temp * temp;
}
}
}
... ...
... ... @@ -86,7 +86,7 @@ public class CacheAbleServiceHelper {
* @param paramMap
* @return
*/
@SearchCacheAble(cacheName = "COMMON_SCENE_QUERY_BY_PARAM", cacheInMinute = 10, excludeParams = { "uid" })
@SearchCacheAble(cacheName = "COMMON_SCENE_QUERY_BY_PARAM", cacheInMinute = 10)
public SearchApiResult queryProductListByRecallParam(CommonRecallParam commonRecallParam) {
try {
// 1、获取参数
... ...
package com.yoho.search.service.recall.model;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
... ... @@ -20,11 +21,15 @@ public class CommonRecallParam extends SearchCacheAbleParam {
private Map<String, String> paramMap;
private BoolQueryBuilder extendMustFilter;
private List<SortBuilder<?>> sortBuilders = new ArrayList<SortBuilder<?>>();
private int uid;
private int page;
private int viewNum;
public CommonRecallParam(Map<String, String> paramMap){
public CommonRecallParam(Map<String, String> paramMap,int uid,int page,int viewNum){
this.paramMap = paramMap;
this.uid = uid;
this.page = page;
this.viewNum = viewNum;
}
public Map<String, String> getParamMap() {
... ... @@ -47,36 +52,26 @@ public class CommonRecallParam extends SearchCacheAbleParam {
this.sortBuilders = sortBuilders;
}
public int getPage() {
return page;
public int getUid() {
return uid;
}
public void setPage(int page) {
this.page = page;
public int getPage() {
return page;
}
public int getViewNum() {
return viewNum;
}
public void setViewNum(int viewNum) {
this.viewNum = viewNum;
}
@Override
public String searchCacheKey() {
public String toCacheKeyValue() {
StringBuilder sb = new StringBuilder();
List<String> excludeParams = new ArrayList<String>();
excludeParams.add("uid");
if (page > 0) {
excludeParams.add("page");
}
if (viewNum > 0) {
excludeParams.add("viewNum");
}
List<String> excludeParams = Arrays.asList("uid","page","viewNum");
sb.append("paramMap=").append(HttpServletRequestUtils.genParamStringWithExcludeParams(paramMap,excludeParams));
sb.append("&extendMustFilter=").append(extendMustFilter==null?"":extendMustFilter.toString());
sb.append("&sortBuilders=").append(sortBuilders==null||sortBuilders.isEmpty()?"":sortBuilders.toString());
sb.append("&uid=").append(uid);
sb.append("&page=").append(page);
sb.append("&viewNum=").append(viewNum);
return sb.toString();
... ...
... ... @@ -2,6 +2,7 @@ package com.yoho.search.service.recall.model;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang.StringUtils;
... ... @@ -39,11 +40,12 @@ public class CommonRecallResult extends SearchCacheAbleParam implements Serializ
for (CommonRecallSkn commonRecallSkn : recallSknList) {
productSkns.add(commonRecallSkn.getProductSkn());
}
Collections.sort(productSkns);
return productSkns;
}
@Override
public String searchCacheKey() {
public String toCacheKeyValue() {
return StringUtils.join(toSknList(),",");
}
... ...