Authored by hugufei

default数据使用人气和点击率做a/b test

... ... @@ -8,6 +8,7 @@ import com.yoho.search.base.utils.Transfer;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.recall.common.ABUserPartitionUtils;
import com.yoho.search.recall.scene.beans.builder.UserRecallRequestBuilder;
import com.yoho.search.recall.scene.beans.cache.SknReturnInfoCacheBean;
import com.yoho.search.recall.scene.beans.cache.UserRecallCacheBean;
... ... @@ -53,6 +54,7 @@ public class SceneRecallProductListService {
/**
* 个性化召回列表入口1
*
* @param paramMap
* @return
*/
... ... @@ -76,6 +78,7 @@ public class SceneRecallProductListService {
/**
* 个性化召回列表入口2
*
* @param userRecallRequest
* @param page
* @return
... ... @@ -83,17 +86,17 @@ public class SceneRecallProductListService {
public SearchApiResult recallProductList(UserRecallRequest userRecallRequest, int page) {
//1、判断第一页是要需要查缓存【不查询缓存时,只添加缓存,以保证用户数据的实时性】
boolean ignoreQueryCache = false;
if(page==1 && userRecallRequest.hasUidOrUdid() && !searchDynamicConfigService.searchPersionalNewStrategyFirstPageCacheOpen()){
if (page == 1 && userRecallRequest.hasUidOrUdid() && !searchDynamicConfigService.searchPersionalNewStrategyFirstPageCacheOpen()) {
ignoreQueryCache = true;
}
//2、执行召回
long begin = System.currentTimeMillis();
UserRecallResponse userRecallResponse = userRecallCacheBean.queryRecallResult(userRecallRequest,ignoreQueryCache);
RECALL_NEW_LOGGER.info("SceneRecallProductListService[1]-queryRecallResult,cost is [{}]", System.currentTimeMillis()-begin);
UserRecallResponse userRecallResponse = userRecallCacheBean.queryRecallResult(userRecallRequest, ignoreQueryCache);
RECALL_NEW_LOGGER.info("SceneRecallProductListService[1]-queryRecallResult,cost is [{}]", System.currentTimeMillis() - begin);
//3、根据召回结果查询商品信息
List<Map<String, Object>> productList = this.queryProductList(userRecallRequest, userRecallResponse,page, userRecallRequest.getPageSize());
List<Map<String, Object>> productList = this.queryProductList(userRecallRequest, userRecallResponse, page, userRecallRequest.getPageSize());
//4、构造返回结果
JSONObject dataMap = new JSONObject();
... ... @@ -107,6 +110,7 @@ public class SceneRecallProductListService {
/**
* 根据召回结果查询商品列表
*
* @param userRecallRequest
* @param userRecallResponse
* @param page
... ... @@ -118,33 +122,33 @@ public class SceneRecallProductListService {
int recallTotalPage = userRecallResponse.getRecallTotalPage();
//2、在召回结果中则直接根据skn去查询
List<RecallSknInfo> recallSknInfos = null;
if(page<=recallTotalPage){
recallSknInfos = CollectionUtils.safeSubList(userRecallResponse.getSknList(),(page-1)*pageSize,page*pageSize);
}else{
recallSknInfos = this.queryProductSknByFilterSkn(userRecallRequest, userRecallResponse.getSknList(), page-recallTotalPage, pageSize);
if (page <= recallTotalPage) {
recallSknInfos = CollectionUtils.safeSubList(userRecallResponse.getSknList(), (page - 1) * pageSize, page * pageSize);
} else {
recallSknInfos = this.queryProductSknByFilterSkn(userRecallRequest, userRecallResponse.getSknList(), page - recallTotalPage, pageSize);
}
//3、获取召回结果的skn
List<Integer> productSknList = this.getProductSknList(recallSknInfos);
//4、获取商品的返回信息
long begin = System.currentTimeMillis();
List<Map<String, Object>> productInfoList = sknReturnInfoCacheBean.queryProductListBySkn(productSknList,productSknList.size());
RECALL_NEW_LOGGER.info("SceneRecallProductListService[2].queryProductListBySkn,cost is [{}]", System.currentTimeMillis()-begin);
List<Map<String, Object>> productInfoList = sknReturnInfoCacheBean.queryProductListBySkn(productSknList, productSknList.size());
RECALL_NEW_LOGGER.info("SceneRecallProductListService[2].queryProductListBySkn,cost is [{}]", System.currentTimeMillis() - begin);
//5、填充召回类型
Map<Integer,RecallSknInfo> sknRecallTypeMap = CollectionUtils.toMap(recallSknInfos, new Transfer<RecallSknInfo, Integer>() {
Map<Integer, RecallSknInfo> sknRecallTypeMap = CollectionUtils.toMap(recallSknInfos, new Transfer<RecallSknInfo, Integer>() {
@Override
public Integer transfer(RecallSknInfo recallSknInfo) {
return recallSknInfo.getProductSkn();
}
});
for(Map<String, Object> productInfo: productInfoList){
int productSkn = MapUtils.getIntValue(productInfo,"product_skn",0);
for (Map<String, Object> productInfo : productInfoList) {
int productSkn = MapUtils.getIntValue(productInfo, "product_skn", 0);
RecallSknInfo recallSknInfo = sknRecallTypeMap.get(productSkn);
if(recallSknInfo==null || recallSknInfo.getRecallType()==null){
productInfo.put("recall_type", StrategyEnum.DEFAULT.name());
}else{
productInfo.put("recall_type",recallSknInfo.getRecallType());
if (recallSknInfo == null || recallSknInfo.getRecallType() == null) {
productInfo.put("recall_type", StrategyEnum.DEFAULT_HEAT_VALUE.name());
} else {
productInfo.put("recall_type", recallSknInfo.getRecallType());
}
}
return productInfoList;
... ... @@ -152,53 +156,57 @@ public class SceneRecallProductListService {
/**
* 过滤掉已召回的skn,并按人气排序
*
* @param recallSknInfos
* @param realPage
* @param pageSize
* @return
*/
private List<RecallSknInfo> queryProductSknByFilterSkn(UserRecallRequest userRecallRequest, List<RecallSknInfo> recallSknInfos, int realPage, int pageSize){
private List<RecallSknInfo> queryProductSknByFilterSkn(UserRecallRequest userRecallRequest, List<RecallSknInfo> recallSknInfos, int realPage, int pageSize) {
long begin = System.currentTimeMillis();
SearchParam searchParam = new SearchParam();
//0、策略区分
StrategyEnum strategyEnum = ABUserPartitionUtils.isAUserComplete(userRecallRequest.getUid(), userRecallRequest.getUdid()) ? StrategyEnum.DEFAULT_HEAT_VALUE : StrategyEnum.DEFAULT_CTR_VALUE;
//1、设置query
SearchParam searchParam = new SearchParam();
searchParam.setQuery(userRecallRequest.getParamQueryFilter().getParamQuery());
//2、设置filter
List<Integer> notProductSkns = new ArrayList<>();
for (RecallSknInfo recallSknInfo:recallSknInfos ){
for (RecallSknInfo recallSknInfo : recallSknInfos) {
notProductSkns.add(recallSknInfo.getProductSkn());
}
BoolQueryBuilder filter = userRecallRequest.getParamQueryFilter().getParamFilter();
filter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.productSkn,notProductSkns));
filter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, notProductSkns));
searchParam.setFiter(filter);
//3、设置分页参数
searchParam.setOffset((realPage-1)*pageSize);
searchParam.setOffset((realPage - 1) * pageSize);
searchParam.setSize(pageSize);
//4、设置IncludeFields
searchParam.setIncludeFields(Arrays.asList(ProductIndexEsField.productSkn));
//5、设置排序
List<SortBuilder<?>> sortBuilders = new ArrayList<>();
if (strategyEnum.equals(StrategyEnum.DEFAULT_HEAT_VALUE)) {
sortBuilders.add(SortBuilderHelper.getHeatValueDescSort());
} else {
sortBuilders.add(SortBuilderHelper.getCtrValueDescSort());
}
sortBuilders.add(SortBuilderHelper.getSevendayMoneyDescSort());
sortBuilders.add(SortBuilderHelper.getIdDescSort());
searchParam.setSortBuilders(sortBuilders);
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX,searchParam);
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
//6、构造返回结果
List<RecallSknInfo> results = new ArrayList<>();
for (Map<String, Object> product : searchResult.getResultList()) {
results.add(new RecallSknInfo(MapUtils.getIntValue(product,ProductIndexEsField.productSkn,0), StrategyEnum.DEFAULT.name()));
results.add(new RecallSknInfo(MapUtils.getIntValue(product, ProductIndexEsField.productSkn, 0), strategyEnum.name()));
}
RECALL_NEW_LOGGER.info("SceneRecallProductListService[1.5].queryProductSknByFilterSkn,cost is [{}]", System.currentTimeMillis()-begin);
RECALL_NEW_LOGGER.info("SceneRecallProductListService[1.5].queryProductSknByFilterSkn,cost is [{}]", System.currentTimeMillis() - begin);
return results;
}
private List<Integer> getProductSknList(List<RecallSknInfo> recallSknInfos){
private List<Integer> getProductSknList(List<RecallSknInfo> recallSknInfos) {
List<Integer> productSknList = new ArrayList<>();
for (RecallSknInfo recallSknInfo:recallSknInfos ){
for (RecallSknInfo recallSknInfo : recallSknInfos) {
productSknList.add(recallSknInfo.getProductSkn());
}
return productSknList;
... ...
... ... @@ -31,7 +31,9 @@ public enum StrategyEnum {
COMMON_RECALL_VALUE(1),//页面兜底召回-包含个性化【随机200取40】
COMMON(0),//兜底,其他策略数量足够时召回来的商品会丢弃
DEFAULT(-1);//其他,无视即可
DEFAULT_HEAT_VALUE(-1),//第四部分做A/B测试
DEFAULT_CTR_VALUE(-2);//第四部分做A/B测试
private Integer priority;
... ...