Authored by 胡古飞

搜索新增一种召回

... ... @@ -12,6 +12,7 @@ public class UserPersonalFactor {
private List<Integer> recommendSknList;
private List<Integer> realTimeSimilarSknList;
private List<Integer> realTimeYoutubeSknList;
private List<Integer> realTimeYtbNewSknList;
private List<SortPriceAreas> sortPriceAreasList;
... ... @@ -25,6 +26,7 @@ public class UserPersonalFactor {
this.recommendSknList = new ArrayList<>();
this.realTimeSimilarSknList = new ArrayList<>();
this.realTimeYoutubeSknList = new ArrayList<>();
this.realTimeYtbNewSknList = new ArrayList<>();
this.sortPriceAreasList = new ArrayList<>();
... ... @@ -35,10 +37,19 @@ public class UserPersonalFactor {
this.orderAvaiable = false;
}
public UserPersonalFactor(List<Integer> recommendSknList, List<Integer> realTimeSimilarSknList,List<Integer> realTimeYoutubeSknList, List<SortPriceAreas> sortPriceAreasList, List<SortBrand> realTimeSortBrandList, List<SortBrand> vectorRnnSortBrandList, List<SortBrand> vectorW2vSortBrandList,boolean orderAvaiable) {
public UserPersonalFactor(List<Integer> recommendSknList,
List<Integer> realTimeSimilarSknList,
List<Integer> realTimeYoutubeSknList,
List<Integer> realTimeYtbNewSknList,
List<SortPriceAreas> sortPriceAreasList,
List<SortBrand> realTimeSortBrandList,
List<SortBrand> vectorRnnSortBrandList,
List<SortBrand> vectorW2vSortBrandList,
boolean orderAvaiable) {
this.recommendSknList = recommendSknList;
this.realTimeSimilarSknList = realTimeSimilarSknList;
this.realTimeYoutubeSknList = realTimeYoutubeSknList;
this.realTimeYtbNewSknList = realTimeYtbNewSknList;
this.sortPriceAreasList = sortPriceAreasList;
this.realTimeSortBrandList = realTimeSortBrandList;
this.vectorRnnSortBrandList = vectorRnnSortBrandList;
... ... @@ -74,31 +85,39 @@ public class UserPersonalFactor {
return realTimeYoutubeSknList;
}
public List<Integer> getRealTimeYtbNewSknList() {
return realTimeYtbNewSknList;
}
public boolean isOrderAvaiable() {
return orderAvaiable;
}
/**
* 判断用户个性化数据是否都为空
*
* @return
*/
public boolean isUserPersonalFactorEmpty(){
if(!CollectionUtils.isEmpty(this.recommendSknList)){
public boolean isUserPersonalFactorEmpty() {
if (!CollectionUtils.isEmpty(this.recommendSknList)) {
return false;
}
if (!CollectionUtils.isEmpty(this.realTimeSimilarSknList)) {
return false;
}
if(!CollectionUtils.isEmpty(this.realTimeSimilarSknList)){
if (!CollectionUtils.isEmpty(this.realTimeYoutubeSknList)) {
return false;
}
if(!CollectionUtils.isEmpty(this.realTimeYoutubeSknList)){
if (!CollectionUtils.isEmpty(this.realTimeYtbNewSknList)) {
return false;
}
if(!CollectionUtils.isEmpty(this.realTimeSortBrandList)){
if (!CollectionUtils.isEmpty(this.realTimeSortBrandList)) {
return false;
}
if(!CollectionUtils.isEmpty(this.vectorRnnSortBrandList)){
if (!CollectionUtils.isEmpty(this.vectorRnnSortBrandList)) {
return false;
}
if(!CollectionUtils.isEmpty(this.vectorW2vSortBrandList)){
if (!CollectionUtils.isEmpty(this.vectorW2vSortBrandList)) {
return false;
}
return true;
... ...
package com.yoho.search.restapi.tools;
import com.yoho.search.core.personalized.service.BidataServiceCaller;
import com.yoho.search.core.personalized.service.PersonalVersionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping(value = "/tools")
public class BigdataTestController {
@Autowired
private PersonalVersionManager personalVersionManager;
@Autowired
private BidataServiceCaller bidataServiceCaller;
@RequestMapping(value = "/bigdataServiceTest")
public Map<String, Object> bigdataServiceTets(Integer uid) {
Map<String, Object> results = new HashMap<>();
//大数据目前推荐的版本
String bigDataRecomDateStr = personalVersionManager.getBigDataRecomDateStr();
results.put("bigDataRecomDateStr", bigDataRecomDateStr == null ? "" : bigDataRecomDateStr);
results.put("bigDataRecomDateStrFeatures", bidataServiceCaller.getUserVectorFeature(uid.toString(), bigDataRecomDateStr));
//zk中目前的版本
String currentVersionInZk = personalVersionManager.getCurrentVersionInZk();
results.put("currentVersionInZk", currentVersionInZk == null ? "" : currentVersionInZk);
results.put("currentVersionInZkFeatures", bidataServiceCaller.getUserVectorFeature(uid.toString(), currentVersionInZk));
//用户性别偏好
results.put("userGenderFeature", bidataServiceCaller.getUserGenderFeature(uid.toString()));
//用户尺码偏好
results.put("userFavoriteSizes", bidataServiceCaller.getUserFavoriteSizes(uid.toString()));
//用户个性化因子
results.put("userPersionalFactor", bidataServiceCaller.queryUserPersionalFactor(uid, null, null));
return results;
}
}
... ...
... ... @@ -41,11 +41,11 @@ public class QueryUserPersionalFactorBean {
long begin = System.currentTimeMillis();
//2、获取用户的个性化因子
UserPersonalFactorRsp userFactor = userComponent.queryUserPersionalFactor(userRecallRequest.getUid(), userRecallRequest.getUdid(), pageFactor.getMisortIds());
RecallLoggerHelper.info("QueryUserPersionalFactorBean[1]:queryUserPersionalFactor. uid is[{}],udid is[{}], cost is[{}ms]", userRecallRequest.getUid(), userRecallRequest.getUdid(), System.currentTimeMillis()-begin);
RecallLoggerHelper.info("QueryUserPersionalFactorBean[1]:queryUserPersionalFactor. uid is[{}],udid is[{}], cost is[{}ms]", userRecallRequest.getUid(), userRecallRequest.getUdid(), System.currentTimeMillis() - begin);
//3、构造结果
begin = System.currentTimeMillis();
UserPersonalFactor userPersonalFactor = this.buildUserPersonalFactor(userRecallRequest, pageFactor, userFactor);
RecallLoggerHelper.info("QueryUserPersionalFactorBean[2]:buildUserPersonalFactor. uid is[{}],udid is[{}], cost is[{}ms]", userRecallRequest.getUid(), userRecallRequest.getUdid(), System.currentTimeMillis()-begin);
RecallLoggerHelper.info("QueryUserPersionalFactorBean[2]:buildUserPersonalFactor. uid is[{}],udid is[{}], cost is[{}ms]", userRecallRequest.getUid(), userRecallRequest.getUdid(), System.currentTimeMillis() - begin);
return userPersonalFactor;
} catch (Exception e) {
RecallLoggerHelper.error(e.getMessage(), e);
... ... @@ -57,53 +57,56 @@ public class QueryUserPersionalFactorBean {
//1、构造品类价格带
List<SortPriceAreas> sortPriceAreasList = this.getSortPriceAreasListWithSort(userFactor, pageFactor);
//2、构造推荐的skn列表
List<Integer> recommendSknList = userFactor.getRecommendSknList();
List<Integer> realTimeSimilarSknList = userFactor.getRealTimeSimilarSknList();
List<Integer> realTimeYoutubeSknList = userFactor.getRealTimeYoutubeSknList();
//3、获取页面中存在的所有的key
//2、获取页面中存在的所有的品类品牌key
Set<String> pageSortBrandKeys = new HashSet<>();
for (SortBrand pageSortBrand : pageFactor.getSortBrandList()) {
pageSortBrandKeys.add(pageSortBrand.key());
}
//4、构造实时【品类+品牌】
//3、构造实时【品类+品牌】
int recSortBrandCount = recallConfigService.querySortBrandConfigCount(userRecallRequest, SortBrandType.REC_SORT_BRAND, 12);
List<SortBrand> realTimeSortBrandList = this.joinRealTimeSortBrandList(pageSortBrandKeys, userFactor.getRealTimeSortBrandList(), recSortBrandCount);
//5、构造临时过滤对象
//4、构造临时过滤对象
Set<String> filterSortBrandKeys = new HashSet<>();
for (SortBrand existSortBrand : realTimeSortBrandList) {
filterSortBrandKeys.add(existSortBrand.key());
}
//6、构造基于RNN向量的【品牌+品牌】,去除实时的品类和品牌
//5、构造基于RNN向量的【品牌+品牌】,去除实时的品类和品牌
int vectorRNNSortBrandCount = recallConfigService.querySortBrandConfigCount(userRecallRequest, SortBrandType.VEC_RNN_SORT_BRAND, 0);
List<SortBrand> vectorRnnSortBrandList = sortBrandVectorComponent.queryVectorSortBrandList(pageFactor, filterSortBrandKeys, userFactor.getBrandVector(), userFactor.getSortBrandVector(), true, vectorRNNSortBrandCount);
for (SortBrand existSortBrand : vectorRnnSortBrandList) {
filterSortBrandKeys.add(existSortBrand.key());
}
//7、构造基于W2V向量的【品牌+品牌】,去除实时的品类和品牌
//6、构造基于W2V向量的【品牌+品牌】,去除实时的品类和品牌
int vecW2vSortBrandCount = recallConfigService.querySortBrandConfigCount(userRecallRequest, SortBrandType.VEC_W2V_SORT_BRAND, 12);
List<SortBrand> vectorW2vSortBrandList = sortBrandVectorComponent.queryVectorSortBrandList(pageFactor, filterSortBrandKeys, userFactor.getBrandVectorW2v(), userFactor.getSortBrandVectorW2v(), false, vecW2vSortBrandCount);
for (SortBrand existSortBrand : vectorW2vSortBrandList) {
filterSortBrandKeys.add(existSortBrand.key());
}
//8、是否下过单
boolean orderAvaiable = userFactor.isOrderAvailable();
//9、构造个性化结果
UserPersonalFactor userPersonalFactor = new UserPersonalFactor(recommendSknList, realTimeSimilarSknList, realTimeYoutubeSknList, sortPriceAreasList, realTimeSortBrandList, vectorRnnSortBrandList, vectorW2vSortBrandList,orderAvaiable);
//10、如果个性化结果为空,再取配置的品类品牌数据
//7、构造个性化结果
UserPersonalFactor userPersonalFactor = new UserPersonalFactor(
userFactor.getRecommendSknList(),
userFactor.getRealTimeSimilarSknList(),
userFactor.getRealTimeYoutubeSknList(),
userFactor.getRealTimeYtbNewSknList(),
sortPriceAreasList,
realTimeSortBrandList,
vectorRnnSortBrandList,
vectorW2vSortBrandList,
userFactor.isOrderAvailable());
//8、如果个性化结果为空,再取配置的品类品牌数据
if (userPersonalFactor.isUserPersonalFactorEmpty()) {
int configSortBrandCount = recallConfigService.querySortBrandConfigCount(userRecallRequest, SortBrandType.CONFIG_SORT_BRAND, 12);
List<SortBrand> configSortBrandList = recallConfigService.randomConfigSortBrand(pageFactor, pageSortBrandKeys, filterSortBrandKeys, configSortBrandCount);
userPersonalFactor.setConfigSortBrandList(configSortBrandList);
}
//11、返回最终结果
//9、返回最终结果
return userPersonalFactor;
}
... ...
... ... @@ -45,6 +45,10 @@ public class UserPersionalFactorComponent {
if (rsp.getRealTimeYoutubeSknList() == null) {
rsp.setRealTimeYoutubeSknList(new ArrayList<>());
}
//realTimeYtbNewSknList
if (rsp.getRealTimeYtbNewSknList() == null) {
rsp.setRealTimeYtbNewSknList(new ArrayList<>());
}
//价格带
if (rsp.getSortPriceAreasList() == null) {
rsp.setSortPriceAreasList(new ArrayList<>());
... ...
... ... @@ -19,10 +19,7 @@ import com.yoho.search.service.recall.helper.ExtendFilterHelper;
import com.yoho.search.service.recall.helper.RecallLoggerHelper;
import com.yoho.search.service.recall.helper.StrategyHelper;
import com.yoho.search.service.recall.strategy.StrategyEnum;
import com.yoho.search.service.recall.strategy.impls.IRecallSknStrategy;
import com.yoho.search.service.recall.strategy.impls.RealTimeSimilarSknStrategy;
import com.yoho.search.service.recall.strategy.impls.RealTimeYoutuboSknStrategy;
import com.yoho.search.service.recall.strategy.impls.RecommendSknStrategy;
import com.yoho.search.service.recall.strategy.impls.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
... ... @@ -59,7 +56,7 @@ public class SknRecallRecallRequestResponseBuilder {
public List<RecallRequestResponse> buildRecallRequestsForSkn(UserRecallRequest userRecallRequest, UserPersonalFactor userPersonalFactor) {
try {
List<Integer> filterSknList = new ArrayList<>();
//1、获取实时点击skn的配置
// 1、获取实时点击skn的配置
int recSknCount = recallConfigService.queryStrategyConfigSize(userRecallRequest, StrategyEnum.REC_SKN, 0);
if (recSknCount > 0 && userPersonalFactor.getRecommendSknList() != null) {
filterSknList.addAll(userPersonalFactor.getRecommendSknList());
... ... @@ -68,7 +65,7 @@ public class SknRecallRecallRequestResponseBuilder {
}
RecallLoggerHelper.infoDetail(userRecallRequest, "buildRecallRequestsForSkn, REC_SKN size is [{}]", recSknCount);
//2、获取相似skn的配置
//2、获取相似skn-youtube的配置
int youtubeSknCount = recallConfigService.queryStrategyConfigSize(userRecallRequest, StrategyEnum.RT_YOUTUBE_SKN, 0);
if (youtubeSknCount > 0 && userPersonalFactor.getRealTimeYoutubeSknList() != null) {
filterSknList.addAll(userPersonalFactor.getRealTimeYoutubeSknList());
... ... @@ -77,16 +74,25 @@ public class SknRecallRecallRequestResponseBuilder {
}
RecallLoggerHelper.infoDetail(userRecallRequest, "buildRecallRequestsForSkn, RT_YOUTUBE_SKN size is [{}]", youtubeSknCount);
//3、获取相似skn的配置
//3、获取相似skn-youtube-new的配置
int ytbNewSknCount = recallConfigService.queryStrategyConfigSize(userRecallRequest, StrategyEnum.RT_YTB_NEW_SKN, 0);
if (ytbNewSknCount > 0 && userPersonalFactor.getRealTimeYtbNewSknList() != null) {
filterSknList.addAll(userPersonalFactor.getRealTimeYtbNewSknList());
} else {
ytbNewSknCount = 0;
}
RecallLoggerHelper.infoDetail(userRecallRequest, "buildRecallRequestsForSkn, RT_YTB_NEW_SKN size is [{}]", ytbNewSknCount);
//4、获取相似skn的配置
int rtSimSknCount = recallConfigService.queryStrategyConfigSize(userRecallRequest, StrategyEnum.RT_SIM_SKN, 0);
if (rtSimSknCount > 0 && userPersonalFactor.getRealTimeSimilarSknList() != null) {
filterSknList.addAll(userPersonalFactor.getRealTimeSimilarSknList());
} else {
rtSimSknCount = 0;
}
RecallLoggerHelper.infoDetail(userRecallRequest, "buildRecallRequestsForSkn, rtSimSknCount size is [{}]", rtSimSknCount);
RecallLoggerHelper.infoDetail(userRecallRequest, "buildRecallRequestsForSkn, RT_SIM_SKN size is [{}]", rtSimSknCount);
//4、执行查询
//5、执行查询
if (filterSknList.isEmpty()) {
return new ArrayList<>();
}
... ... @@ -96,7 +102,8 @@ public class SknRecallRecallRequestResponseBuilder {
} else {
sknResults = this.filterRecommedSknListByEs(userRecallRequest, filterSknList);
}
//5、构造结果
//6、构造结果
List<RecallRequestResponse> results = new ArrayList<>();
ParamQueryFilter paramQueryFilter = userRecallRequest.getParamQueryFilter();
if (recSknCount > 0) {
... ... @@ -105,6 +112,9 @@ public class SknRecallRecallRequestResponseBuilder {
if (youtubeSknCount > 0) {
results.addAll(this.buildResults(paramQueryFilter, userPersonalFactor.getRealTimeYoutubeSknList(), RealTimeYoutuboSknStrategy.class, sknResults, youtubeSknCount));
}
if (ytbNewSknCount > 0) {
results.addAll(this.buildResults(paramQueryFilter, userPersonalFactor.getRealTimeYtbNewSknList(), RealTimeYtbNewSknStrategy.class, sknResults, ytbNewSknCount));
}
if (rtSimSknCount > 0) {
results.addAll(this.buildResults(paramQueryFilter, userPersonalFactor.getRealTimeSimilarSknList(), RealTimeSimilarSknStrategy.class, sknResults, rtSimSknCount));
}
... ...
package com.yoho.search.service.recall.helper;
import com.yoho.search.service.recall.strategy.StrategyEnum;
import com.yoho.search.service.recall.strategy.impls.IRecallSknStrategy;
import com.yoho.search.service.recall.strategy.impls.RealTimeSimilarSknStrategy;
import com.yoho.search.service.recall.strategy.impls.RealTimeYoutuboSknStrategy;
import com.yoho.search.service.recall.strategy.impls.RecommendSknStrategy;
import com.yoho.search.service.recall.strategy.impls.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Constructor;
public class StrategyHelper {
private static final Logger logger = LoggerFactory.getLogger(StrategyHelper.class);
/**
* 兜底找回类型枚举
*
... ... @@ -23,7 +26,16 @@ public class StrategyHelper {
* @return
*/
public static boolean isRecommendSknStrage(StrategyEnum strategy) {
if (strategy.equals(StrategyEnum.REC_SKN) || strategy.equals(StrategyEnum.RT_SIM_SKN) || strategy.equals(StrategyEnum.RT_YOUTUBE_SKN)) {
if (strategy.equals(StrategyEnum.REC_SKN)) {
return true;
}
if (strategy.equals(StrategyEnum.RT_SIM_SKN)) {
return true;
}
if (strategy.equals(StrategyEnum.RT_YOUTUBE_SKN)) {
return true;
}
if (strategy.equals(StrategyEnum.RT_YTB_NEW_SKN)) {
return true;
}
return false;
... ... @@ -35,13 +47,24 @@ public class StrategyHelper {
* @return
*/
public static IRecallSknStrategy getRecallSknStrategy(Class<? extends IRecallSknStrategy> clazz, Integer skn) {
if (clazz.isAssignableFrom(RecommendSknStrategy.class)) {
return new RecommendSknStrategy(skn);
}
if (clazz.isAssignableFrom(RealTimeYoutuboSknStrategy.class)) {
return new RealTimeYoutuboSknStrategy(skn);
try {
Constructor<? extends IRecallSknStrategy> c = clazz.getConstructor(Integer.class);
return c.newInstance(skn);
}catch (Exception e){
logger.error(e.getMessage(),e);
return null;
}
return new RealTimeSimilarSknStrategy(skn);
//
// if (clazz.isAssignableFrom(RecommendSknStrategy.class)) {
// return new RecommendSknStrategy(skn);
// }
// if (clazz.isAssignableFrom(RealTimeYoutuboSknStrategy.class)) {
// return new RealTimeYoutuboSknStrategy(skn);
// }
// if (clazz.isAssignableFrom(RealTimeYtbNewSknStrategy.class)) {
// return new RealTimeYtbNewSknStrategy(skn);
// }
// return new RealTimeSimilarSknStrategy(skn);
}
... ...
... ... @@ -11,8 +11,9 @@ public enum StrategyEnum {
DIRECT_TRAIN_SORT_PRICE(896),//直通车-品类价格带
REC_SKN(800),//实时推荐的skn
RT_SIM_SKN(798),//实时推荐的skn的相似skn
RT_YOUTUBE_SKN(799),//实时推荐的skn的相似skn-基于YOUTUBE
RT_SIM_SKN(797),//实时推荐的skn的相似skn
RT_YOUTUBE_SKN(798),//实时推荐的skn的相似skn-基于YOUTUBE
RT_YTB_NEW_SKN(799),//实时推荐的skn的相似skn-基于YOUTUBE-NEW
ADD_FLOW(700),//流量补偿
NEW_SHOP(699),//新开店铺
... ...
package com.yoho.search.service.recall.strategy.impls;
import com.yoho.search.service.recall.strategy.StrategyEnum;
public class RealTimeYtbNewSknStrategy extends IRecallSknStrategy {
public RealTimeYtbNewSknStrategy(Integer recommendSkn) {
super(recommendSkn);
}
@Override
public StrategyEnum strategtEnum() {
return StrategyEnum.RT_YTB_NEW_SKN;
}
}
... ...