...
|
...
|
@@ -6,7 +6,9 @@ import java.util.List; |
|
|
import java.util.Map;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
import com.yoho.search.base.utils.ConvertUtils;
|
|
|
import com.yoho.search.service.recall.config.SpecialShopConstants;
|
|
|
import org.apache.commons.collections.CollectionUtils;
|
|
|
import org.apache.commons.collections.MapUtils;
|
|
|
import org.apache.commons.lang.StringUtils;
|
|
|
import org.elasticsearch.common.lucene.search.function.CombineFunction;
|
...
|
...
|
@@ -34,252 +36,257 @@ import com.yoho.search.service.scene.general.ProductCountService; |
|
|
@Component
|
|
|
public class FunctionScoreSearchHelper {
|
|
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(FunctionScoreSearchHelper.class);
|
|
|
private static final Logger logger = LoggerFactory.getLogger(FunctionScoreSearchHelper.class);
|
|
|
|
|
|
@Autowired
|
|
|
private SearchCommonHelper searchCommonHelper;
|
|
|
@Autowired
|
|
|
private PersonalVectorFeatureSearch personalVectorFeatureSearch;
|
|
|
@Autowired
|
|
|
private SearchDynamicConfigService dynamicConfig;
|
|
|
@Autowired
|
|
|
private SearchScorerFactory searchScorerFactory;
|
|
|
@Autowired
|
|
|
private ProductCountService productCountService;
|
|
|
@Autowired
|
|
|
private SearchCommonHelper searchCommonHelper;
|
|
|
@Autowired
|
|
|
private PersonalVectorFeatureSearch personalVectorFeatureSearch;
|
|
|
@Autowired
|
|
|
private SearchDynamicConfigService dynamicConfig;
|
|
|
@Autowired
|
|
|
private SearchScorerFactory searchScorerFactory;
|
|
|
@Autowired
|
|
|
private ProductCountService productCountService;
|
|
|
|
|
|
// 普通个性化的时间维度
|
|
|
private static final FirstShelveTimeScore COMMON_FIRST_SHELVE_SCORE = new FirstShelveTimeScore(30, 7, 23);
|
|
|
// 新品到着的个性化时间维度
|
|
|
private static final FirstShelveTimeScore NEW_REC_FIRST_SHELVE_SCORE = new FirstShelveTimeScore(4, 1, 3);
|
|
|
// 模糊搜索的个性化时间维度
|
|
|
private static final FirstShelveTimeScore FUZZY_FIRST_SHELVE_SCORE = new FirstShelveTimeScore(90, 60, 30);
|
|
|
// 普通个性化的时间维度
|
|
|
private static final FirstShelveTimeScore COMMON_FIRST_SHELVE_SCORE = new FirstShelveTimeScore(30, 7, 23);
|
|
|
// 新品到着的个性化时间维度
|
|
|
private static final FirstShelveTimeScore NEW_REC_FIRST_SHELVE_SCORE = new FirstShelveTimeScore(4, 1, 3);
|
|
|
// 模糊搜索的个性化时间维度
|
|
|
private static final FirstShelveTimeScore FUZZY_FIRST_SHELVE_SCORE = new FirstShelveTimeScore(90, 60, 30);
|
|
|
|
|
|
/**
|
|
|
* 添加打分规则
|
|
|
*
|
|
|
* @param queryBuilder
|
|
|
* @param boolQueryBuilder
|
|
|
* @param paramMap
|
|
|
* @return
|
|
|
*/
|
|
|
public QueryBuilder buildFunctionScoreQueryBuild(QueryBuilder queryBuilder, BoolQueryBuilder boolQueryBuilder, Map<String, String> paramMap) {
|
|
|
// 1、构造persionalFilter
|
|
|
BoolQueryBuilder persionalFilter = this.genPersionalFilter(queryBuilder, boolQueryBuilder);
|
|
|
// 2、获取打分器
|
|
|
String pageId = MapUtils.getString(paramMap, SearchRequestParams.PARAM_SEARCH_PAGEID, "0");
|
|
|
List<IScorer> scorers = this.getScorers(pageId, persionalFilter, paramMap);
|
|
|
if (scorers == null || scorers.isEmpty()) {
|
|
|
return new FunctionScoreQueryBuilder(queryBuilder);
|
|
|
}
|
|
|
// 3、构造functionScoreQueryBuilder
|
|
|
YohoFilterFunctionBuilders yohoFilterFunctionBuilders = new YohoFilterFunctionBuilders();
|
|
|
for (IScorer iScorer : scorers) {
|
|
|
if(iScorer!=null){
|
|
|
iScorer.addScorer(yohoFilterFunctionBuilders);
|
|
|
}
|
|
|
}
|
|
|
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder, yohoFilterFunctionBuilders.getFilterFunctionBuilders());
|
|
|
// 4、设置打分模式
|
|
|
functionScoreQueryBuilder.boostMode(CombineFunction.MULTIPLY);
|
|
|
return functionScoreQueryBuilder;
|
|
|
}
|
|
|
/**
|
|
|
* 添加打分规则
|
|
|
*
|
|
|
* @param queryBuilder
|
|
|
* @param boolQueryBuilder
|
|
|
* @param paramMap
|
|
|
* @return
|
|
|
*/
|
|
|
public QueryBuilder buildFunctionScoreQueryBuild(QueryBuilder queryBuilder, BoolQueryBuilder boolQueryBuilder, Map<String, String> paramMap) {
|
|
|
// 1、构造persionalFilter
|
|
|
BoolQueryBuilder persionalFilter = this.genPersionalFilter(queryBuilder, boolQueryBuilder);
|
|
|
// 2、获取打分器
|
|
|
String pageId = MapUtils.getString(paramMap, SearchRequestParams.PARAM_SEARCH_PAGEID, "0");
|
|
|
List<IScorer> scorers = this.getScorers(pageId, persionalFilter, paramMap);
|
|
|
if (scorers == null || scorers.isEmpty()) {
|
|
|
return new FunctionScoreQueryBuilder(queryBuilder);
|
|
|
}
|
|
|
// 3、构造functionScoreQueryBuilder
|
|
|
YohoFilterFunctionBuilders yohoFilterFunctionBuilders = new YohoFilterFunctionBuilders();
|
|
|
for (IScorer iScorer : scorers) {
|
|
|
if (iScorer != null) {
|
|
|
iScorer.addScorer(yohoFilterFunctionBuilders);
|
|
|
}
|
|
|
}
|
|
|
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder, yohoFilterFunctionBuilders.getFilterFunctionBuilders());
|
|
|
// 4、设置打分模式
|
|
|
functionScoreQueryBuilder.boostMode(CombineFunction.MULTIPLY);
|
|
|
return functionScoreQueryBuilder;
|
|
|
}
|
|
|
|
|
|
private BoolQueryBuilder genPersionalFilter(QueryBuilder queryBuilder, BoolQueryBuilder boolQueryBuilder) {
|
|
|
BoolQueryBuilder persionalFilter = QueryBuilders.boolQuery();
|
|
|
if (queryBuilder != null) {
|
|
|
persionalFilter.must(queryBuilder);
|
|
|
}
|
|
|
if (boolQueryBuilder != null) {
|
|
|
persionalFilter.must(boolQueryBuilder);
|
|
|
}
|
|
|
return persionalFilter;
|
|
|
}
|
|
|
private BoolQueryBuilder genPersionalFilter(QueryBuilder queryBuilder, BoolQueryBuilder boolQueryBuilder) {
|
|
|
BoolQueryBuilder persionalFilter = QueryBuilders.boolQuery();
|
|
|
if (queryBuilder != null) {
|
|
|
persionalFilter.must(queryBuilder);
|
|
|
}
|
|
|
if (boolQueryBuilder != null) {
|
|
|
persionalFilter.must(boolQueryBuilder);
|
|
|
}
|
|
|
return persionalFilter;
|
|
|
}
|
|
|
|
|
|
private List<IScorer> getScorers(String pageId, BoolQueryBuilder persionalFilter, Map<String, String> paramMap) {
|
|
|
List<IScorer> scorers = null;
|
|
|
switch (pageId) {
|
|
|
case SearchPageIdDefine.PAGE_ID_SORT:
|
|
|
scorers = this.getSortPageScorers(persionalFilter, paramMap);
|
|
|
break;
|
|
|
case SearchPageIdDefine.PAGE_ID_SEARCH:
|
|
|
scorers = this.getFuzzyPageScorers(persionalFilter, paramMap);
|
|
|
break;
|
|
|
case SearchPageIdDefine.PAGE_ID_NEW:
|
|
|
scorers = this.getNewArrivePageScorers(persionalFilter, paramMap);
|
|
|
break;
|
|
|
default:
|
|
|
scorers = this.getOtherPageScorers(persionalFilter, paramMap);
|
|
|
break;
|
|
|
}
|
|
|
return scorers;
|
|
|
}
|
|
|
private List<IScorer> getScorers(String pageId, BoolQueryBuilder persionalFilter, Map<String, String> paramMap) {
|
|
|
List<IScorer> scorers = null;
|
|
|
switch (pageId) {
|
|
|
case SearchPageIdDefine.PAGE_ID_SORT:
|
|
|
scorers = this.getSortPageScorers(persionalFilter, paramMap);
|
|
|
break;
|
|
|
case SearchPageIdDefine.PAGE_ID_SEARCH:
|
|
|
scorers = this.getFuzzyPageScorers(persionalFilter, paramMap);
|
|
|
break;
|
|
|
case SearchPageIdDefine.PAGE_ID_NEW:
|
|
|
scorers = this.getNewArrivePageScorers(persionalFilter, paramMap);
|
|
|
break;
|
|
|
default:
|
|
|
scorers = this.getOtherPageScorers(persionalFilter, paramMap);
|
|
|
break;
|
|
|
}
|
|
|
return scorers;
|
|
|
}
|
|
|
|
|
|
// 品类页的打分器
|
|
|
private List<IScorer> getSortPageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) {
|
|
|
List<IScorer> scorers = new ArrayList<IScorer>();
|
|
|
// 1、不是默认品类页,返回空列表
|
|
|
if (!searchCommonHelper.isSortPageDefault(paramMap)) {
|
|
|
return scorers;
|
|
|
}
|
|
|
// 2、获取通用打分器
|
|
|
scorers.addAll(this.getCommonScorers(persionalFilter, paramMap));
|
|
|
// 3、添加首次上架时间的打分器
|
|
|
scorers.add(searchScorerFactory.getFirstShelveTimeScorer(getOtherPageShelveTimeScore()));
|
|
|
// 4、品类页添加加分SKN的打分器
|
|
|
scorers.add(searchScorerFactory.getAddScoreSknsScorer());
|
|
|
return scorers;
|
|
|
}
|
|
|
|
|
|
// 品类页的打分器
|
|
|
private List<IScorer> getSortPageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) {
|
|
|
List<IScorer> scorers = new ArrayList<IScorer>();
|
|
|
// 1、不是默认品类页,返回空列表
|
|
|
if (!searchCommonHelper.isSortPageDefault(paramMap)) {
|
|
|
return scorers;
|
|
|
}
|
|
|
// 2、获取通用打分器
|
|
|
scorers.addAll(this.getCommonScorers(persionalFilter, paramMap));
|
|
|
// 3、添加首次上架时间的打分器
|
|
|
scorers.add(searchScorerFactory.getFirstShelveTimeScorer(getOtherPageShelveTimeScore()));
|
|
|
// 4、品类页添加加分SKN的打分器
|
|
|
scorers.add(searchScorerFactory.getAddScoreSknsScorer());
|
|
|
return scorers;
|
|
|
}
|
|
|
|
|
|
// 模糊搜索页的打分器
|
|
|
private List<IScorer> getFuzzyPageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) {
|
|
|
List<IScorer> scorers = new ArrayList<>();
|
|
|
// 1、不是默认搜索类页,返回空列表
|
|
|
if (!searchCommonHelper.isFuzzySearchPageDefault(paramMap)) {
|
|
|
return scorers;
|
|
|
}
|
|
|
// 2、获取通用打分器
|
|
|
scorers.addAll(this.getCommonScorers(persionalFilter, paramMap));
|
|
|
// 3、添加首次上架时间的打分器
|
|
|
scorers.add(searchScorerFactory.getFirstShelveTimeScorer(FUZZY_FIRST_SHELVE_SCORE));
|
|
|
// 4、添加频道搜索
|
|
|
scorers.add(searchScorerFactory.getChannelSearchScorer(paramMap));
|
|
|
// 5、添加线下可售商品打分器
|
|
|
scorers.add(searchScorerFactory.getOfflineSaleOnlyScorer());
|
|
|
// 6、添加关键词完全匹配的打分器
|
|
|
String query = MapUtils.getString(paramMap, SearchRequestParams.PARAM_SEARCH_QUERY);
|
|
|
if(StringUtils.isNotBlank(query)){
|
|
|
scorers.add(searchScorerFactory.getCsBrandKeyWordScorer(query));
|
|
|
}
|
|
|
// 7、添加特殊店铺的打分器
|
|
|
scorers.add(searchScorerFactory.getSpecialShopScorer(SpecialShopConstants.DOWNGRADE_SHOPIDS, SpecialShopConstants.DOWNGRADE_SHOP_WEIGHT));
|
|
|
return scorers;
|
|
|
}
|
|
|
|
|
|
// 新品到着页的打分器
|
|
|
private List<IScorer> getNewArrivePageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) {
|
|
|
List<IScorer> scorers = new ArrayList<IScorer>();
|
|
|
if (searchCommonHelper.isNewRecPageDefault(paramMap)) {
|
|
|
scorers.addAll(this.getCommonScorers(persionalFilter, paramMap));
|
|
|
scorers.add(searchScorerFactory.getFirstShelveTimeScorer(getNewArrivalPageShelveTimeScore()));
|
|
|
} else if (searchCommonHelper.isNewRecHeatValueDescSearch(paramMap)) {
|
|
|
scorers.add(searchScorerFactory.getNewArriveHeatDescScorer());// 新品到着页的人气值排序
|
|
|
}
|
|
|
return scorers;
|
|
|
}
|
|
|
// 模糊搜索页的打分器
|
|
|
private List<IScorer> getFuzzyPageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) {
|
|
|
List<IScorer> scorers = new ArrayList<>();
|
|
|
// 1、不是默认搜索类页,返回空列表
|
|
|
if (!searchCommonHelper.isFuzzySearchPageDefault(paramMap)) {
|
|
|
return scorers;
|
|
|
}
|
|
|
// 2、获取通用打分器
|
|
|
scorers.addAll(this.getCommonScorers(persionalFilter, paramMap));
|
|
|
// 3、添加首次上架时间的打分器
|
|
|
scorers.add(searchScorerFactory.getFirstShelveTimeScorer(FUZZY_FIRST_SHELVE_SCORE));
|
|
|
// 4、添加频道搜索
|
|
|
scorers.add(searchScorerFactory.getChannelSearchScorer(paramMap));
|
|
|
// 5、添加线下可售商品打分器
|
|
|
scorers.add(searchScorerFactory.getOfflineSaleOnlyScorer());
|
|
|
// 6、添加关键词完全匹配的打分器
|
|
|
String query = MapUtils.getString(paramMap, SearchRequestParams.PARAM_SEARCH_QUERY);
|
|
|
if (StringUtils.isNotBlank(query)) {
|
|
|
scorers.add(searchScorerFactory.getCsBrandKeyWordScorer(query));
|
|
|
}
|
|
|
// 7、添加特殊店铺的打分器
|
|
|
scorers.add(searchScorerFactory.getSpecialShopScorer(SpecialShopConstants.DOWNGRADE_SHOPIDS, SpecialShopConstants.DOWNGRADE_SHOP_WEIGHT));
|
|
|
return scorers;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 其他页面的打分规则
|
|
|
*
|
|
|
* @param persionalFilter
|
|
|
* @param paramMap
|
|
|
*/
|
|
|
private List<IScorer> getOtherPageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) {
|
|
|
List<IScorer> scorers = new ArrayList<IScorer>();
|
|
|
if (!searchCommonHelper.isOrderEmpty(paramMap)) {
|
|
|
return scorers;
|
|
|
}
|
|
|
scorers.addAll(this.getCommonScorers(persionalFilter, paramMap));
|
|
|
scorers.add(searchScorerFactory.getFirstShelveTimeScorer(getOtherPageShelveTimeScore()));
|
|
|
return scorers;
|
|
|
}
|
|
|
// 新品到着页的打分器
|
|
|
private List<IScorer> getNewArrivePageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) {
|
|
|
List<IScorer> scorers = new ArrayList<IScorer>();
|
|
|
if (searchCommonHelper.isNewRecPageDefault(paramMap)) {
|
|
|
scorers.addAll(this.getCommonScorers(persionalFilter, paramMap));
|
|
|
scorers.add(searchScorerFactory.getFirstShelveTimeScorer(getNewArrivalPageShelveTimeScore()));
|
|
|
} else if (searchCommonHelper.isNewRecHeatValueDescSearch(paramMap)) {
|
|
|
scorers.add(searchScorerFactory.getNewArriveHeatDescScorer());// 新品到着页的人气值排序
|
|
|
}
|
|
|
return scorers;
|
|
|
}
|
|
|
|
|
|
// 公用的打分器
|
|
|
private List<IScorer> getCommonScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) {
|
|
|
// 1、传了order,则都不生效
|
|
|
if (!searchCommonHelper.isOrderEmpty(paramMap)) {
|
|
|
return new ArrayList<IScorer>();
|
|
|
}
|
|
|
List<IScorer> scorers = new ArrayList<IScorer>();
|
|
|
// 2、全球购商品
|
|
|
scorers.add(searchScorerFactory.getGlobalProductSearch(paramMap));
|
|
|
// 3、一高三低商品降分[非新品并且零交际的商品]
|
|
|
scorers.add(searchScorerFactory.getProblemProductScorer());
|
|
|
// 4、first_product_skn
|
|
|
scorers.add(searchScorerFactory.getFirstProductSknScorer(paramMap));
|
|
|
// 5、断码商品
|
|
|
//scorers.add(searchScorerFactory.getBreakSizeProductScorer(paramMap));
|
|
|
// 6、基于向量的个性化打分
|
|
|
scorers.add(this.getPersonalVectorFeatureScorer(persionalFilter, paramMap));
|
|
|
return scorers;
|
|
|
}
|
|
|
/**
|
|
|
* 其他页面的打分规则
|
|
|
*
|
|
|
* @param persionalFilter
|
|
|
* @param paramMap
|
|
|
*/
|
|
|
private List<IScorer> getOtherPageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) {
|
|
|
List<IScorer> scorers = new ArrayList<IScorer>();
|
|
|
if (!searchCommonHelper.isOrderEmpty(paramMap)) {
|
|
|
return scorers;
|
|
|
}
|
|
|
scorers.addAll(this.getCommonScorers(persionalFilter, paramMap));
|
|
|
scorers.add(searchScorerFactory.getFirstShelveTimeScorer(getOtherPageShelveTimeScore()));
|
|
|
return scorers;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 个性化的打分器
|
|
|
*
|
|
|
* @param persionalFilter
|
|
|
* @param paramMap
|
|
|
* @return
|
|
|
*/
|
|
|
private IScorer getPersonalVectorFeatureScorer(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) {
|
|
|
// 1、判断是否开启了个性化搜索
|
|
|
if (!searchCommonHelper.isNeedPersonalSearch(paramMap)) {
|
|
|
return null;
|
|
|
}
|
|
|
// 2、获取PersonalizedSearch
|
|
|
PersonalizedSearch personalizedSearch = personalVectorFeatureSearch.getPersonalizedSearch(paramMap);
|
|
|
if (personalizedSearch == null) {
|
|
|
return null;
|
|
|
}
|
|
|
// 3、为个性化打分添加filter条件
|
|
|
BoolQueryBuilder scoreFilter = productCountService.genScoreFilter(persionalFilter);
|
|
|
return searchScorerFactory.getFeatureFactorScorer(scoreFilter, personalizedSearch.getUserVectorFeature(), personalizedSearch.getVectorFeatureVersion());
|
|
|
}
|
|
|
// 公用的打分器
|
|
|
private List<IScorer> getCommonScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) {
|
|
|
// 1、传了order,则都不生效
|
|
|
if (!searchCommonHelper.isOrderEmpty(paramMap)) {
|
|
|
return new ArrayList<IScorer>();
|
|
|
}
|
|
|
List<IScorer> scorers = new ArrayList<IScorer>();
|
|
|
// 2、全球购商品
|
|
|
scorers.add(searchScorerFactory.getGlobalProductSearch(paramMap));
|
|
|
// 3、一高三低商品降分[非新品并且零交际的商品]
|
|
|
scorers.add(searchScorerFactory.getProblemProductScorer());
|
|
|
// 4、first_product_skn
|
|
|
scorers.add(searchScorerFactory.getFirstProductSknScorer(paramMap));
|
|
|
// 5、断码商品
|
|
|
//scorers.add(searchScorerFactory.getBreakSizeProductScorer(paramMap));
|
|
|
// 6、基于向量的个性化打分
|
|
|
scorers.add(this.getPersonalVectorFeatureScorer(persionalFilter, paramMap));
|
|
|
return scorers;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 直接使用商品特征的向量用来做个性化打分
|
|
|
*
|
|
|
* @param queryBuilder
|
|
|
* @param productVectorFeature
|
|
|
* @return
|
|
|
*/
|
|
|
public QueryBuilder buildFunctionScoreQueryBuildWithProductFeature(QueryBuilder queryBuilder, String productVectorFeature) {
|
|
|
// 1. 获取商品特征向量
|
|
|
if (StringUtils.isBlank(productVectorFeature)) {
|
|
|
return queryBuilder;
|
|
|
}
|
|
|
// 2. 传入参数调用脚本,以商品特征代替用户特征
|
|
|
String[] productVectorFeatures = productVectorFeature.split("\\|", 2);
|
|
|
if (productVectorFeatures.length != 2) {
|
|
|
return queryBuilder;
|
|
|
}
|
|
|
IScorer scorer = searchScorerFactory.getFeatureFactorScorer(queryBuilder, productVectorFeatures[1], productVectorFeatures[0]);
|
|
|
YohoFilterFunctionBuilders yohoFilterFunctionBuilders = new YohoFilterFunctionBuilders();
|
|
|
if(scorer!=null){
|
|
|
scorer.addScorer(yohoFilterFunctionBuilders);
|
|
|
}
|
|
|
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder,yohoFilterFunctionBuilders.getFilterFunctionBuilders());
|
|
|
return functionScoreQueryBuilder;
|
|
|
}
|
|
|
/**
|
|
|
* 个性化的打分器
|
|
|
*
|
|
|
* @param persionalFilter
|
|
|
* @param paramMap
|
|
|
* @return
|
|
|
*/
|
|
|
private IScorer getPersonalVectorFeatureScorer(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) {
|
|
|
// 1、判断是否开启了个性化搜索
|
|
|
if (!searchCommonHelper.isNeedPersonalSearch(paramMap)) {
|
|
|
return null;
|
|
|
}
|
|
|
// 2、获取PersonalizedSearch
|
|
|
PersonalizedSearch personalizedSearch = personalVectorFeatureSearch.queryPersonalizedSearch(paramMap);
|
|
|
if (personalizedSearch == null) {
|
|
|
return null;
|
|
|
}
|
|
|
// 3、为个性化打分添加filter条件
|
|
|
BoolQueryBuilder scoreFilter = productCountService.genScoreFilter(persionalFilter);
|
|
|
return searchScorerFactory.getFeatureFactorScorer(scoreFilter, personalizedSearch.getVectorVersion(), personalizedSearch.getVectorFeatures());
|
|
|
}
|
|
|
|
|
|
// 新品到着页的根据首次上架时间衰减函数规则值
|
|
|
private FirstShelveTimeScore getNewArrivalPageShelveTimeScore() {
|
|
|
try {
|
|
|
String values = dynamicConfig.getNewArrivalPageDecayRuleValue();
|
|
|
List<Integer> valueList = Arrays.asList(values.split(",")).stream().map(Integer::valueOf).collect(Collectors.toList());
|
|
|
Assert.isTrue(valueList.size() == 2, "For " + values);
|
|
|
Integer scale = valueList.get(0) - valueList.get(1);
|
|
|
Assert.isTrue(scale.intValue() > 0, "For " + values);
|
|
|
return new FirstShelveTimeScore(valueList.get(0), valueList.get(1), scale);
|
|
|
} catch (Exception e) {
|
|
|
logger.warn(e.getMessage(), e);
|
|
|
return NEW_REC_FIRST_SHELVE_SCORE;
|
|
|
}
|
|
|
}
|
|
|
/**
|
|
|
* 直接使用商品特征的向量用来做个性化打分
|
|
|
*
|
|
|
* @param queryBuilder
|
|
|
* @param productVectorFeature
|
|
|
* @return
|
|
|
*/
|
|
|
public QueryBuilder buildFunctionScoreQueryBuildWithProductFeature(QueryBuilder queryBuilder, String productVectorFeature) {
|
|
|
// 1. 获取商品特征向量
|
|
|
if (StringUtils.isBlank(productVectorFeature)) {
|
|
|
return queryBuilder;
|
|
|
}
|
|
|
// 2. 传入参数调用脚本,以商品特征代替用户特征
|
|
|
String[] productVectorFeatures = productVectorFeature.split("\\|", 2);
|
|
|
if (productVectorFeatures.length != 2) {
|
|
|
return queryBuilder;
|
|
|
}
|
|
|
// 3、参数检测
|
|
|
String featureVersion = productVectorFeatures[0];
|
|
|
List<Double> featureFactors = ConvertUtils.stringToDoubleList(productVectorFeatures[1], ",");
|
|
|
if (StringUtils.isBlank(featureVersion) || CollectionUtils.isEmpty(featureFactors)) {
|
|
|
return queryBuilder;
|
|
|
}
|
|
|
//4、构造scorer
|
|
|
IScorer scorer = searchScorerFactory.getFeatureFactorScorer(queryBuilder, featureVersion, featureFactors);
|
|
|
YohoFilterFunctionBuilders yohoFilterFunctionBuilders = new YohoFilterFunctionBuilders();
|
|
|
scorer.addScorer(yohoFilterFunctionBuilders);
|
|
|
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder, yohoFilterFunctionBuilders.getFilterFunctionBuilders());
|
|
|
return functionScoreQueryBuilder;
|
|
|
}
|
|
|
|
|
|
// 非新品到着页的根据首次上架时间衰减函数规则值
|
|
|
private FirstShelveTimeScore getOtherPageShelveTimeScore() {
|
|
|
try {
|
|
|
String values = dynamicConfig.getOtherPageDecayRuleValue();
|
|
|
List<Integer> valueList = Arrays.asList(values.split(",")).stream().map(Integer::valueOf).collect(Collectors.toList());
|
|
|
Assert.isTrue(valueList.size() == 2, "For " + values);
|
|
|
Integer scale = valueList.get(0) - valueList.get(1);
|
|
|
Assert.isTrue(scale.intValue() > 0, "For " + values);
|
|
|
return new FirstShelveTimeScore(valueList.get(0), valueList.get(1), scale);
|
|
|
} catch (Exception e) {
|
|
|
logger.warn(e.getMessage(), e);
|
|
|
return COMMON_FIRST_SHELVE_SCORE;
|
|
|
}
|
|
|
}
|
|
|
// 新品到着页的根据首次上架时间衰减函数规则值
|
|
|
private FirstShelveTimeScore getNewArrivalPageShelveTimeScore() {
|
|
|
try {
|
|
|
String values = dynamicConfig.getNewArrivalPageDecayRuleValue();
|
|
|
List<Integer> valueList = Arrays.asList(values.split(",")).stream().map(Integer::valueOf).collect(Collectors.toList());
|
|
|
Assert.isTrue(valueList.size() == 2, "For " + values);
|
|
|
Integer scale = valueList.get(0) - valueList.get(1);
|
|
|
Assert.isTrue(scale.intValue() > 0, "For " + values);
|
|
|
return new FirstShelveTimeScore(valueList.get(0), valueList.get(1), scale);
|
|
|
} catch (Exception e) {
|
|
|
logger.warn(e.getMessage(), e);
|
|
|
return NEW_REC_FIRST_SHELVE_SCORE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 非新品到着页的根据首次上架时间衰减函数规则值
|
|
|
private FirstShelveTimeScore getOtherPageShelveTimeScore() {
|
|
|
try {
|
|
|
String values = dynamicConfig.getOtherPageDecayRuleValue();
|
|
|
List<Integer> valueList = Arrays.asList(values.split(",")).stream().map(Integer::valueOf).collect(Collectors.toList());
|
|
|
Assert.isTrue(valueList.size() == 2, "For " + values);
|
|
|
Integer scale = valueList.get(0) - valueList.get(1);
|
|
|
Assert.isTrue(scale.intValue() > 0, "For " + values);
|
|
|
return new FirstShelveTimeScore(valueList.get(0), valueList.get(1), scale);
|
|
|
} catch (Exception e) {
|
|
|
logger.warn(e.getMessage(), e);
|
|
|
return COMMON_FIRST_SHELVE_SCORE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
} |
...
|
...
|
|