...
|
...
|
@@ -3,8 +3,11 @@ package com.yoho.search.service.personalized; |
|
|
import java.util.ArrayList;
|
|
|
import java.util.Collections;
|
|
|
import java.util.Comparator;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.HashSet;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.Set;
|
|
|
|
|
|
import org.apache.commons.lang.StringUtils;
|
|
|
import org.elasticsearch.common.lucene.search.function.FieldValueFactorFunction;
|
...
|
...
|
@@ -18,7 +21,6 @@ import org.springframework.beans.factory.annotation.Autowired; |
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import com.yoho.search.base.utils.HttpServletRequestUtils;
|
|
|
import com.yoho.search.base.utils.ISearchConstants;
|
|
|
import com.yoho.search.core.personalized.PConsts;
|
|
|
import com.yoho.search.service.personalized.model.SearchFeature;
|
|
|
import com.yoho.search.service.service.SearchDynamicConfigService;
|
...
|
...
|
@@ -45,29 +47,39 @@ public final class PersonalizedSearch { |
|
|
return pageId;
|
|
|
}
|
|
|
|
|
|
private List<SearchFeature> getUserSearchFeatures(String uid, String pageId) {
|
|
|
private Map<String, List<SearchFeature>> getUserGroupSearchFeatures(String uid, String pageId) {
|
|
|
// 1、获取用户信息和页面信息
|
|
|
List<SearchFeature> sfRedis = userFeatures.getUserFeaturesFromRedis(uid, pageId);
|
|
|
if (sfRedis == null || sfRedis.isEmpty()) {
|
|
|
return new ArrayList<SearchFeature>();
|
|
|
return new HashMap<String, List<SearchFeature>>();
|
|
|
}
|
|
|
// 2、对 用户权重进行排序,should个数超过一定数量, 按权重值desc排序, 截取数据
|
|
|
List<SearchFeature> searchFeatures = null;
|
|
|
if (sfRedis.size() > ISearchConstants.PERSONALIZED_SEARCH_SHOULD_MAX) {
|
|
|
// 按照boost进行排序
|
|
|
Collections.sort(sfRedis, new Comparator<SearchFeature>() {
|
|
|
@Override
|
|
|
public int compare(SearchFeature left, SearchFeature right) {
|
|
|
Float fleft = Float.valueOf(left.getBoost());
|
|
|
Float fright = Float.valueOf(right.getBoost());
|
|
|
return fright.compareTo(fleft);
|
|
|
}
|
|
|
});
|
|
|
searchFeatures = sfRedis.subList(0, ISearchConstants.PERSONALIZED_SEARCH_SHOULD_MAX);
|
|
|
} else {
|
|
|
searchFeatures = sfRedis;
|
|
|
// 按照boost进行排序
|
|
|
Collections.sort(sfRedis, new Comparator<SearchFeature>() {
|
|
|
@Override
|
|
|
public int compare(SearchFeature left, SearchFeature right) {
|
|
|
Float fleft = Float.valueOf(left.getBoost());
|
|
|
Float fright = Float.valueOf(right.getBoost());
|
|
|
return fright.compareTo(fleft);
|
|
|
}
|
|
|
});
|
|
|
// 2、按用户特征的维度分组
|
|
|
Map<String, List<SearchFeature>> useFeatureGroup = new HashMap<String, List<SearchFeature>>();
|
|
|
for (SearchFeature searchFeature : sfRedis) {
|
|
|
String targetParam = searchFeature.getTargetParam();
|
|
|
List<SearchFeature> userFeatureList = useFeatureGroup.get(targetParam);
|
|
|
if (userFeatureList == null) {
|
|
|
userFeatureList = new ArrayList<>();
|
|
|
useFeatureGroup.put(targetParam, userFeatureList);
|
|
|
}
|
|
|
if (searchFeature.getBoost() <= 0) {
|
|
|
continue;
|
|
|
}
|
|
|
if (userFeatureList.size() > dynamicConfig.userPersonalizedMaxCount()) {
|
|
|
continue;
|
|
|
}
|
|
|
userFeatureList.add(searchFeature);
|
|
|
}
|
|
|
return searchFeatures;
|
|
|
return useFeatureGroup;
|
|
|
}
|
|
|
|
|
|
public void addPersonalizedFieldValueFactor(FunctionScoreQueryBuilder functionScoreQueryBuilder, Map<String, String> paramMap) {
|
...
|
...
|
@@ -84,26 +96,36 @@ public final class PersonalizedSearch { |
|
|
// 1、获取用户特征息信息
|
|
|
String uid = this.getUidFromParamMap(paramMap);
|
|
|
String pageId = this.getPageIdFromParamMap(paramMap);
|
|
|
List<SearchFeature> userSearchFeatures = this.getUserSearchFeatures(uid, pageId);
|
|
|
if (userSearchFeatures == null || userSearchFeatures.isEmpty()) {
|
|
|
Map<String, List<SearchFeature>> userGroupFeatures = this.getUserGroupSearchFeatures(uid, pageId);
|
|
|
if (userGroupFeatures == null || userGroupFeatures.isEmpty()) {
|
|
|
return;
|
|
|
}
|
|
|
// 2、对用户权重 进行加分[以乘的方式]
|
|
|
float maxBoost = this.getMaxBoost(userSearchFeatures);// 获取用户最大的boost,已调整boost值
|
|
|
boolean isFuzzySearch = this.isFuzzySearch(pageId);
|
|
|
for (SearchFeature searchFeature : userSearchFeatures) {
|
|
|
float boost = searchFeature.getBoost();
|
|
|
if (boost < 0) {
|
|
|
boost = 0;
|
|
|
}
|
|
|
float weight = boost / maxBoost;// 非模糊查询时,用户特征最大加分值为3
|
|
|
if (isFuzzySearch) {
|
|
|
weight = weight * 0.5f;// 模糊查询时,用户特征最大加分值为1.5
|
|
|
} else {
|
|
|
weight = weight * 2f;
|
|
|
// 2、保存已经操作过的值
|
|
|
Set<String> filteredKeySet = new HashSet<String>();
|
|
|
for (List<SearchFeature> userFeatures : userGroupFeatures.values()) {
|
|
|
// 2.1 、获取加分基准
|
|
|
float maxBoost = this.getMaxBoost(userFeatures);// 获取用户最大的boost,已调整boost值
|
|
|
boolean isFuzzySearch = this.isFuzzySearch(pageId);
|
|
|
// 2.2 、对用户权重 进行加分[以乘的方式]
|
|
|
for (SearchFeature searchFeature : userFeatures) {
|
|
|
float boost = searchFeature.getBoost();
|
|
|
if (boost <= 0) {
|
|
|
continue;
|
|
|
}
|
|
|
String filteredKey = searchFeature.getTargetParam() + "_" + searchFeature.getParamValues();
|
|
|
if (filteredKeySet.contains(filteredKey)) {
|
|
|
continue;
|
|
|
}
|
|
|
filteredKeySet.add(filteredKey);
|
|
|
float weight = boost / maxBoost;// 非模糊查询时,用户特征最大加分值为3
|
|
|
if (isFuzzySearch) {
|
|
|
weight = weight * 0.1f;// 模糊查询时,用户特征最大加分值为1.1
|
|
|
} else {
|
|
|
weight = weight * 2f;// 非模糊查询时,用户特征最大加分值为2[三种维度同时满足,则weight为8]
|
|
|
}
|
|
|
functionScoreQueryBuilder.add(QueryBuilders.termQuery(searchFeature.getTargetParam(), searchFeature.getParamValues()),
|
|
|
ScoreFunctionBuilders.weightFactorFunction(1 + weight));
|
|
|
}
|
|
|
functionScoreQueryBuilder.add(QueryBuilders.termQuery(searchFeature.getTargetParam(), searchFeature.getParamValues()),
|
|
|
ScoreFunctionBuilders.weightFactorFunction(1 + weight));
|
|
|
}
|
|
|
}
|
|
|
|
...
|
...
|
|