|
|
package com.yoho.search.service.scene.activity;
|
|
|
|
|
|
import com.yoho.search.base.helper.Word2VectorCalculator;
|
|
|
import com.yoho.search.base.utils.CollectionUtils;
|
|
|
import com.yoho.search.cache.beans.AbstractCacheBean;
|
|
|
import com.yoho.search.core.personalized.models.UserPersonalFactorRspNew;
|
|
|
import com.yoho.search.service.recall.beans.persional.UserPersionalFactorComponent;
|
|
|
import com.yoho.search.service.recall.beans.strategy.IStrategy;
|
|
|
import com.yoho.search.service.recall.beans.strategy.impls.SortBrandHeatValueStrategy;
|
|
|
import com.yoho.search.service.recall.beans.vector.BrandVectorCacheBean;
|
|
|
import com.yoho.search.service.recall.models.common.ParamQueryFilter;
|
|
|
import com.yoho.search.service.recall.models.personal.BrandVectorScore;
|
|
|
import com.yoho.search.service.recall.models.personal.UserPersonalFactor;
|
|
|
import com.yoho.search.service.recall.models.req.RecallRequest;
|
|
|
import com.yoho.search.service.recall.models.req.RecallRequestResponse;
|
|
|
import com.yoho.search.service.recall.models.req.UserRecallRequest;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
import java.util.*;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
@Component
|
|
|
public class AggBrandProductCacheBean extends AbstractCacheBean<BrandProductRequest, BrandProductResponse, BrandProductRequestResponse> {
|
|
|
|
|
|
@Autowired
|
|
|
private AggBrandService aggBrandService;
|
|
|
@Autowired
|
|
|
private UserPersionalFactorComponent userComponent;
|
|
|
@Autowired
|
|
|
private BrandVectorCacheBean brandVectorCacheBean;
|
|
|
@Autowired
|
|
|
private BatchBrandProductCacheBean batchBrandProductCacheBean;
|
|
|
|
|
|
/**
|
|
|
* 入口
|
|
|
* @return
|
|
|
*/
|
|
|
public BrandProductResponse queryBrandProductResult(BrandProductRequest brandProductRequest) {
|
|
|
BrandProductRequestResponse brandProductRequestResponse = new BrandProductRequestResponse(brandProductRequest);
|
|
|
bacthFillResponseWithCache(brandProductRequestResponse, false);
|
|
|
return brandProductRequestResponse.getResponse();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
protected boolean useEhCache() {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
protected Map<BrandProductRequest, BrandProductResponse> queryMissCacheRequestResults(List<BrandProductRequestResponse> missCacheRequests) {
|
|
|
Map<BrandProductRequest, BrandProductResponse> results = new HashMap<>();
|
|
|
for (BrandProductRequestResponse request : missCacheRequests) {
|
|
|
BrandProductResponse response = doRealRecall(request.getRequest());
|
|
|
results.put(request.getRequest(), response);
|
|
|
}
|
|
|
return results;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 真正的召回入口
|
|
|
*
|
|
|
* @param brandProductRequest
|
|
|
* @return
|
|
|
*/
|
|
|
private BrandProductResponse doRealRecall(BrandProductRequest brandProductRequest) {
|
|
|
//1 获取个性化的和非个性化的brandId viewNum个
|
|
|
List<AggBrand> aggBrands = aggBrandService.aggBrands(brandProductRequest.getParamQueryFilter());
|
|
|
if (org.springframework.util.CollectionUtils.isEmpty(aggBrands)) {
|
|
|
return null;
|
|
|
}
|
|
|
List<Integer> aggBrandIds = aggBrands.stream().map(AggBrand::getBrandId).collect(Collectors.toList());
|
|
|
List<Integer> userPersonalbrandIds = new ArrayList<>();
|
|
|
if (brandProductRequest.hasUidOrUdid()) {
|
|
|
UserPersonalFactorRspNew userFactor = userComponent.queryUserPersionalFactor(brandProductRequest.getUid(), brandProductRequest.getUdid(), null);
|
|
|
userPersonalbrandIds = buildUserPersonalBrandIds(aggBrandIds, userFactor, brandProductRequest.getBrandCount());
|
|
|
}
|
|
|
if (userPersonalbrandIds.size() < brandProductRequest.getBrandCount()) {
|
|
|
aggBrandIds.removeAll(userPersonalbrandIds);
|
|
|
aggBrandIds = CollectionUtils.safeSubList(aggBrandIds, 0, brandProductRequest.getBrandCount() - userPersonalbrandIds.size());
|
|
|
}
|
|
|
|
|
|
//2、获取召回结果
|
|
|
batchRecall(brandProductRequest, userPersonalbrandIds, aggBrandIds);
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
private List<Integer> buildUserPersonalBrandIds(List<Integer> aggBrandIds, UserPersonalFactorRspNew userFactor, int count) {
|
|
|
List<Integer> result = new ArrayList<>();
|
|
|
double userBrandVectorNorm = Word2VectorCalculator.getVectorListNorm(userFactor.getBrandVectorW2v());
|
|
|
List<BrandVectorScore> brandVectorScores = new ArrayList<>();
|
|
|
|
|
|
for (Integer brandId : aggBrandIds) {
|
|
|
List<Double> brandVector = brandVectorCacheBean.queryBrandVector(brandId, false);
|
|
|
if (brandVector == null || brandVector.isEmpty()) {
|
|
|
continue;
|
|
|
}
|
|
|
double score = Word2VectorCalculator.calScore(userFactor.getBrandVectorW2v(), userBrandVectorNorm, brandVector);
|
|
|
brandVectorScores.add(new BrandVectorScore(brandId, score));
|
|
|
}
|
|
|
if (brandVectorScores != null && !brandVectorScores.isEmpty()){
|
|
|
Collections.sort(brandVectorScores, (o1, o2) -> o2.getScore().compareTo(o1.getScore()));//得分高的排在前面
|
|
|
brandVectorScores = CollectionUtils.safeSubList(brandVectorScores, 0, count);
|
|
|
for (BrandVectorScore brandVectorScore : brandVectorScores) {
|
|
|
result.add(brandVectorScore.getBrandId());
|
|
|
}
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
private List<BrandProductRequestResponse> batchRecall(BrandProductRequest brandProductRequest, List<Integer> userPersonalbrandIds, List<Integer> aggBrandIds) {
|
|
|
|
|
|
List<Integer> brandIds = new ArrayList<>(userPersonalbrandIds);
|
|
|
brandIds.addAll(aggBrandIds);
|
|
|
int brandProductCount = brandProductRequest.getBrandProductCount() + 10;
|
|
|
ParamQueryFilter paramQueryFilter = brandProductRequest.getParamQueryFilter();
|
|
|
|
|
|
List<RecallRequest> brandRequests = brandIds.stream().map(brandId -> {
|
|
|
IStrategy strategy = new BrandHeatValueStrategy(brandId, brandProductCount);
|
|
|
return new RecallRequest(paramQueryFilter, strategy);
|
|
|
}).collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
...
|
...
|
|