|
|
package com.yoho.search.recall.scene.beans.cache;
|
|
|
|
|
|
import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
|
|
|
import com.yoho.search.base.utils.ISearchConstants;
|
|
|
import com.yoho.search.base.utils.ProductIndexEsField;
|
|
|
import com.yoho.search.common.cache.impls.EhCache;
|
|
|
import com.yoho.search.common.cache.impls.SearchRedis;
|
|
|
import com.yoho.search.common.cache.model.CacheObject;
|
|
|
import com.yoho.search.core.es.model.SearchParam;
|
|
|
import com.yoho.search.core.es.model.SearchResult;
|
|
|
import com.yoho.search.recall.scene.beans.persional.PageProductIdBitSetComponent;
|
|
|
import com.yoho.search.recall.scene.beans.strategy.impls.RecommendSknStrategy;
|
|
|
import com.yoho.search.recall.scene.models.common.ParamQueryFilter;
|
|
|
import com.yoho.search.recall.scene.models.personal.PageProductIdBitSet;
|
|
|
import com.yoho.search.recall.scene.models.req.RecallRequest;
|
|
|
import com.yoho.search.recall.scene.models.req.RecallRequestResponse;
|
|
|
import com.yoho.search.recall.scene.models.req.RecallResponse;
|
...
|
...
|
@@ -21,31 +26,114 @@ import org.springframework.stereotype.Component; |
|
|
import java.util.*;
|
|
|
|
|
|
@Component
|
|
|
public class SknRecallCacheBean{
|
|
|
public class SknRecallCacheBean {
|
|
|
|
|
|
@Autowired
|
|
|
private SearchCommonService searchCommonService;
|
|
|
@Autowired
|
|
|
private PageProductIdBitSetComponent pageProductIdBitSetComponent;
|
|
|
@Autowired
|
|
|
private SknBaseInfoCacheBean sknBaseInfoCacheBean;
|
|
|
private SearchRedis searchRedis;
|
|
|
@Autowired
|
|
|
private EhCache ehCache;
|
|
|
|
|
|
private static final Boolean recallWithCache = true;
|
|
|
|
|
|
/**
|
|
|
* 将推荐的skn构造成召回对象
|
|
|
*
|
|
|
* @return
|
|
|
*/
|
|
|
public List<RecallRequestResponse> batchRecallRecommedSknList(UserRecallRequest userRecallRequest,List<Integer> recommedSknList,int maxReturnCount){
|
|
|
if(recommedSknList==null || recommedSknList.isEmpty()){
|
|
|
public List<RecallRequestResponse> batchRecallRecommedSknList(UserRecallRequest userRecallRequest, List<Integer> recommedSknList, int maxReturnCount) {
|
|
|
if (recommedSknList == null || recommedSknList.isEmpty()) {
|
|
|
return new ArrayList<>();
|
|
|
}
|
|
|
List<Integer> filterSknList = this.filterRecommedSknList(userRecallRequest,recommedSknList,maxReturnCount);
|
|
|
return this.buildResults(userRecallRequest,filterSknList);
|
|
|
List<Integer> filterSknList;
|
|
|
if (recallWithCache) {
|
|
|
filterSknList = this.filterRecommendWithCache(userRecallRequest, recommedSknList);
|
|
|
} else {
|
|
|
filterSknList = this.filterRecommedSknListByEs(userRecallRequest, recommedSknList);
|
|
|
}
|
|
|
return this.buildResults(userRecallRequest, filterSknList, maxReturnCount);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 从ehcahc或者redis中构造返回结果
|
|
|
* @param userRecallRequest
|
|
|
* @param recommedSknList
|
|
|
* @return
|
|
|
*/
|
|
|
private List<Integer> filterRecommendWithCache(UserRecallRequest userRecallRequest, List<Integer> recommedSknList) {
|
|
|
|
|
|
ParamQueryFilter paramQueryFilter = userRecallRequest.getParamQueryFilter();
|
|
|
RedisKeyBuilder redisKeyBuilder = pageProductIdBitSetComponent.genRedisKeyBuilder(paramQueryFilter);
|
|
|
|
|
|
//1、先从本地缓存获取-本地的是完整的bitset对象
|
|
|
CacheObject cacheObject = ehCache.get(redisKeyBuilder);
|
|
|
if (cacheObject != null) {
|
|
|
return this.filterSknByPageProductIdBitSet(recommedSknList, (BitSet) cacheObject.toObject());
|
|
|
}
|
|
|
|
|
|
//2、直接从redis的bitset缓存结构中过滤
|
|
|
Map<Integer, Boolean> redisQueryResult = searchRedis.getFromBitSet(redisKeyBuilder, recommedSknList);
|
|
|
if (redisQueryResult != null) {
|
|
|
return this.filterSknByRedisQueryResult(recommedSknList, redisQueryResult);
|
|
|
}
|
|
|
|
|
|
//3、执行查询,加添到并本地缓存
|
|
|
PageProductIdBitSet pageProductIdBitSet = pageProductIdBitSetComponent.queryPageProductIdBitSet(userRecallRequest.getParamQueryFilter());
|
|
|
//3.1)添加到本地缓存
|
|
|
this.ehCache.setBitSet(redisKeyBuilder,pageProductIdBitSet.getProductIdBitSet(),pageProductIdBitSetComponent.cacheTimeInMinute());
|
|
|
//3.2)添加到redis缓存
|
|
|
this.searchRedis.setBitSet(redisKeyBuilder,pageProductIdBitSet.getProductIdBitSet(),pageProductIdBitSetComponent.cacheTimeInMinute());
|
|
|
return this.filterSknByPageProductIdBitSet(recommedSknList, pageProductIdBitSet.getProductIdBitSet());
|
|
|
}
|
|
|
|
|
|
private List<Integer> filterRecommedSknList(UserRecallRequest userRecallRequest, List<Integer> recommedSknList,int maxReturnCount){
|
|
|
if(recommedSknList==null || recommedSknList.isEmpty()){
|
|
|
return new ArrayList<>();
|
|
|
/**
|
|
|
* 从bitset对象中构造返回对象
|
|
|
*
|
|
|
* @param recommedSknList
|
|
|
* @param bitSet
|
|
|
* @return
|
|
|
*/
|
|
|
private List<Integer> filterSknByPageProductIdBitSet(List<Integer> recommedSknList, BitSet bitSet) {
|
|
|
List<Integer> results = new ArrayList<>();
|
|
|
for (Integer recommedSkn : recommedSknList) {
|
|
|
if (bitSet.get(recommedSkn)) {
|
|
|
results.add(recommedSkn);
|
|
|
}
|
|
|
}
|
|
|
return results;
|
|
|
}
|
|
|
|
|
|
|
|
|
/**
|
|
|
* 根据redis返回结果按顺序构结果,只返回为true的
|
|
|
*
|
|
|
* @param recommedSknList
|
|
|
* @param redisQueryResult
|
|
|
* @return
|
|
|
*/
|
|
|
private List<Integer> filterSknByRedisQueryResult(List<Integer> recommedSknList, Map<Integer, Boolean> redisQueryResult) {
|
|
|
List<Integer> filterResults = new ArrayList<>();
|
|
|
for (Integer recommedSkn : recommedSknList) {
|
|
|
if (redisQueryResult.getOrDefault(recommedSkn, false)) {
|
|
|
filterResults.add(recommedSkn);
|
|
|
}
|
|
|
}
|
|
|
return filterResults;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 直接从es召回
|
|
|
*
|
|
|
* @param userRecallRequest
|
|
|
* @param recommedSknList
|
|
|
* @return
|
|
|
*/
|
|
|
private List<Integer> filterRecommedSknListByEs(UserRecallRequest userRecallRequest, List<Integer> recommedSknList) {
|
|
|
if (recommedSknList == null || recommedSknList.isEmpty()) {
|
|
|
return new ArrayList<>();
|
|
|
}
|
|
|
//1、构造searchParam
|
|
|
ParamQueryFilter paramQueryFilter = userRecallRequest.getParamQueryFilter();
|
...
|
...
|
@@ -53,7 +141,7 @@ public class SknRecallCacheBean{ |
|
|
searchParam.setQuery(paramQueryFilter.getParamQuery());
|
|
|
BoolQueryBuilder realFilter = QueryBuilders.boolQuery();
|
|
|
realFilter.must(paramQueryFilter.getParamFilter());
|
|
|
realFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.productSkn,recommedSknList));
|
|
|
realFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, recommedSknList));
|
|
|
searchParam.setFiter(realFilter);
|
|
|
|
|
|
//2、设置分页参数
|
...
|
...
|
@@ -74,11 +162,8 @@ public class SknRecallCacheBean{ |
|
|
|
|
|
//5、按顺序构造最终结果
|
|
|
List<Integer> results = new ArrayList<>();
|
|
|
for (Integer recommedSkn: recommedSknList) {
|
|
|
if(results.size()>=maxReturnCount){
|
|
|
continue;
|
|
|
}
|
|
|
if(existsProductSkns.contains(recommedSkn)){
|
|
|
for (Integer recommedSkn : recommedSknList) {
|
|
|
if (existsProductSkns.contains(recommedSkn)) {
|
|
|
results.add(recommedSkn);
|
|
|
}
|
|
|
}
|
...
|
...
|
@@ -87,18 +172,22 @@ public class SknRecallCacheBean{ |
|
|
|
|
|
/**
|
|
|
* 将推荐的skn构造成召回对象
|
|
|
*
|
|
|
* @return
|
|
|
*/
|
|
|
private List<RecallRequestResponse> buildResults(UserRecallRequest userRecallRequest,final List<Integer> recommedSknList){
|
|
|
private List<RecallRequestResponse> buildResults(UserRecallRequest userRecallRequest, final List<Integer> recommedSknList, int maxReturnCount) {
|
|
|
List<RecallRequestResponse> results = new ArrayList<>();
|
|
|
if(recommedSknList==null || recommedSknList.isEmpty()){
|
|
|
if (recommedSknList == null || recommedSknList.isEmpty()) {
|
|
|
return results;
|
|
|
}
|
|
|
ParamQueryFilter paramQueryFilter = userRecallRequest.getParamQueryFilter();
|
|
|
for (Integer recommendSkn : recommedSknList){
|
|
|
RecallRequest recallRequest = new RecallRequest(paramQueryFilter,new RecommendSknStrategy(recommendSkn));
|
|
|
for (Integer recommendSkn : recommedSknList) {
|
|
|
if (results.size() >= maxReturnCount) {
|
|
|
break;
|
|
|
}
|
|
|
RecallRequest recallRequest = new RecallRequest(paramQueryFilter, new RecommendSknStrategy(recommendSkn));
|
|
|
RecallRequestResponse recallRequestResponse = new RecallRequestResponse(recallRequest);
|
|
|
recallRequestResponse.setResponse(new RecallResponse(1L, Arrays.asList(recommendSkn)),false);
|
|
|
recallRequestResponse.setResponse(new RecallResponse(1L, Arrays.asList(recommendSkn)), false);
|
|
|
results.add(recallRequestResponse);
|
|
|
}
|
|
|
return results;
|
...
|
...
|
|