Authored by 胡古飞

update PersonalizedSearch

... ... @@ -8,8 +8,6 @@ import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.common.lucene.search.function.FieldValueFactorFunction;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
... ... @@ -19,11 +17,11 @@ import org.slf4j.LoggerFactory;
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;
import com.yoho.search.service.utils.HttpServletRequestUtils;
@Service
public final class PersonalizedSearch {
... ... @@ -33,63 +31,8 @@ public final class PersonalizedSearch {
@Autowired
private SearchDynamicConfigService dynamicConfig;
private static final float MaxUserFeatureBoost = 50;
private static final Logger PERSONALIZED = LoggerFactory.getLogger("PERSONALIZED");
// public QueryBuilder builder(QueryBuilder queryBuilder, String uid, String
// pageId) {
// QueryBuilder qBuilder = null;
// List<SearchFeature> sfRedis = userFeatures.getUserFeaturesFromRedis(uid,
// pageId);
// if (sfRedis == null || sfRedis.isEmpty()) {
// qBuilder = queryBuilder;
// } else {
// BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// boolQueryBuilder.must(queryBuilder);
//
// List<SearchFeature> searchFeatures = null;
// // should个数超过一定数量, 按权重值desc排序, 截取数据
// 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
// float maxBoost = this.getMaxBoost(searchFeatures);
// boolean isFuzzySearch = this.isFuzzySearch(pageId);
// for (SearchFeature searchFeature : searchFeatures) {
// float boost = searchFeature.getBoost();
// if (isFuzzySearch) {
// boost = getAdaptoredBoost(maxBoost, boost);
// }
// boolQueryBuilder.should(QueryBuilders.termQuery(searchFeature.getTargetParam(),
// searchFeature.getParamValues()).boost(boost));
// }
// qBuilder = boolQueryBuilder;
// }
//
// float factor = getFunctionScoreFactor(pageId);
// // new_score = old_score * log(2 + factor * page_boosts)
// String fieldName = getFuncScoreField(pageId);
// FunctionScoreQueryBuilder fsQueryBuilder = new
// FunctionScoreQueryBuilder(qBuilder);
// fsQueryBuilder.add(
// ScoreFunctionBuilders.fieldValueFactorFunction(fieldName).factor(factor).modifier(FieldValueFactorFunction.Modifier.LOG2P)
// .missing(PConsts.PRODUCT_FUNCTION_MISSING_VALUE)).boostMode(CombineFunction.MULT);
//
// return fsQueryBuilder;
// }
private String getUidFromParamMap(Map<String, String> paramMap) {
return paramMap.get("uid");
}
... ... @@ -102,41 +45,6 @@ public final class PersonalizedSearch {
return pageId;
}
/**
* 针对用户特征,对用户进行加分
*
* @param queryBuilder
* @param uid
* @param pageId
* @return
*/
public QueryBuilder buildPersonalizedQueryBuilder(QueryBuilder queryBuilder, Map<String, String> paramMap) {
PERSONALIZED.info("do personal search , paramString is [{}]", HttpServletRequestUtils.genParamString(paramMap));
// 1、获取用户特征息信息
String uid = this.getUidFromParamMap(paramMap);
String pageId = this.getPageIdFromParamMap(paramMap);
List<SearchFeature> userSearchFeatures = this.getUserSearchFeatures(uid, pageId);
if (userSearchFeatures == null || userSearchFeatures.isEmpty()) {
return queryBuilder;
}
// 2、对用户权重 进行加分
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(queryBuilder);
float maxBoost = this.getMaxBoost(userSearchFeatures);// 获取用户最大的boost,已调整boost值
boolean isFuzzySearch = this.isFuzzySearch(pageId);
for (SearchFeature searchFeature : userSearchFeatures) {
float boost = searchFeature.getBoost();
if (isFuzzySearch) {
boost = getAdaptoredBoost(maxBoost, boost);
}
if (boost < 0) {
boost = 0;
}
boolQueryBuilder.should(QueryBuilders.termQuery(searchFeature.getTargetParam(), searchFeature.getParamValues()).boost(boost));
}
return boolQueryBuilder;
}
private List<SearchFeature> getUserSearchFeatures(String uid, String pageId) {
// 1、获取用户信息和页面信息
List<SearchFeature> sfRedis = userFeatures.getUserFeaturesFromRedis(uid, pageId);
... ... @@ -170,8 +78,9 @@ public final class PersonalizedSearch {
.modifier(FieldValueFactorFunction.Modifier.LOG2P).missing(PConsts.PRODUCT_FUNCTION_MISSING_VALUE);
functionScoreQueryBuilder.add(fieldValueFactorFunctionBuilder);
}
public void addPersonalizedUserFetureFactor(FunctionScoreQueryBuilder functionScoreQueryBuilder, Map<String, String> paramMap) {
PERSONALIZED.info("do personal search , paramString is [{}]", HttpServletRequestUtils.genParamString(paramMap));
// 1、获取用户特征息信息
String uid = this.getUidFromParamMap(paramMap);
String pageId = this.getPageIdFromParamMap(paramMap);
... ... @@ -187,15 +96,17 @@ public final class PersonalizedSearch {
if (boost < 0) {
boost = 0;
}
float weight = 1 + boost / (maxBoost);// 非模糊查询时,用户特征最大加分值为2
float weight = boost / maxBoost;// 非模糊查询时,用户特征最大加分值为3
if (isFuzzySearch) {
weight = 1 + boost / (maxBoost * 10);// 模糊查询时,用户特征最大加分值为1.1
weight = weight * 0.5f;// 模糊查询时,用户特征最大加分值为1.5
} else {
weight = weight * 2f;
}
functionScoreQueryBuilder.add(QueryBuilders.termQuery(searchFeature.getTargetParam(), searchFeature.getParamValues()),
ScoreFunctionBuilders.weightFactorFunction(weight));
ScoreFunctionBuilders.weightFactorFunction(1 + weight));
}
}
private float getMaxBoost(List<SearchFeature> searchFeatures) {
float boost = 0f;
for (SearchFeature searchFeature : searchFeatures) {
... ... @@ -220,21 +131,6 @@ public final class PersonalizedSearch {
return false;
}
/**
* 针对模糊搜索,加分最大值为50
*
* @param maxBoost
* @param currentBoost
* @return
*/
private static float getAdaptoredBoost(float maxBoost, float currentBoost) {
return currentBoost / maxBoost * MaxUserFeatureBoost;
}
public static void main(String[] args) {
System.out.println(getAdaptoredBoost(459.90198f, 109.67697f));
}
private float getFunctionScoreFactor(String pageId) {
float factor = 0.0f;
// 对于模糊搜索, 需要把商品特征的权重得分降低, 其余的按其排序
... ...
... ... @@ -25,19 +25,12 @@ public class FunctionScoreSearchHelper {
private SearchDynamicConfigService dynamicConfig;
static float globalWeight = 0.50f;
static float brandTotalMatchWeight = 3f;
private WeightBuilder genWeightFactorBuilder(float factor) {
return ScoreFunctionBuilders.weightFactorFunction(factor);
}
public QueryBuilder buildFunctionScoreQueryBuild(QueryBuilder queryBuilder, Map<String, String> paramMap) {
// // 个性化时先对用户特征加分
// if (searchCommonHelper.isNeedPersonalSearch(paramMap)) {
// queryBuilder =
// personalizedSearch.buildPersonalizedQueryBuilder(queryBuilder,
// paramMap);
// }
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder);
if (searchCommonHelper.isNeedPersonalSearch(paramMap)) {
personalizedSearch.addPersonalizedUserFetureFactor(functionScoreQueryBuilder, paramMap);
... ... @@ -46,11 +39,6 @@ public class FunctionScoreSearchHelper {
if (searchCommonHelper.containGlobal(paramMap)) {
functionScoreQueryBuilder.add(QueryBuilders.termQuery("isGlobal", "Y"), genWeightFactorBuilder(globalWeight));
}
// if (searchCommonHelper.isFuzzySearchDefault(paramMap)) {
// String queryLowerCase = paramMap.get("query").trim().toLowerCase();
// functionScoreQueryBuilder.add(QueryBuilders.termQuery("brandName.brandName_lowercase",
// queryLowerCase), this.genWeightFactorBuilder(brandTotalMatchWeight));
// }
if (searchCommonHelper.isNeedDeScoreBrandSearch(paramMap)) {
functionScoreQueryBuilder.add(QueryBuilders.termQuery("isForbiddenSortBrand", "1"), ScoreFunctionBuilders.weightFactorFunction(0));
}
... ...