Authored by 胡古飞

Merge branch 'master' into ge-promotion_product

Showing 23 changed files with 857 additions and 274 deletions
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;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.index.query.functionscore.fieldvaluefactor.FieldValueFactorFunctionBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.base.utils.HttpServletRequestUtils;
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 {
... ... @@ -31,63 +33,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");
}
... ... @@ -100,68 +47,88 @@ 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));
// 2、获取用户信息和页面信息
String uid = this.getUidFromParamMap(paramMap);
String pageId = this.getPageIdFromParamMap(paramMap);
private Map<String, List<SearchFeature>> getUserGroupSearchFeatures(String uid, String pageId) {
// 1、获取用户信息和页面信息
List<SearchFeature> sfRedis = userFeatures.getUserFeaturesFromRedis(uid, pageId);
if (sfRedis == null || sfRedis.isEmpty()) {
return queryBuilder;
return new HashMap<String, List<SearchFeature>>();
}
// 3、对 用户权重进行排序,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;
}
// 4、对用户权重 进行加分
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(queryBuilder);
float maxBoost = this.getMaxBoost(searchFeatures);// 获取用户最大的boost,已调整boost值
boolean isFuzzySearch = this.isFuzzySearch(pageId);
for (SearchFeature searchFeature : searchFeatures) {
float boost = searchFeature.getBoost();
if (isFuzzySearch) {
boost = getAdaptoredBoost(maxBoost, boost);
// 按照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(boost<0){
boost = 0;
if (searchFeature.getBoost() <= 0) {
continue;
}
boolQueryBuilder.should(QueryBuilders.termQuery(searchFeature.getTargetParam(), searchFeature.getParamValues()).boost(boost));
if (userFeatureList.size() > dynamicConfig.userPersonalizedMaxCount()) {
continue;
}
userFeatureList.add(searchFeature);
}
return boolQueryBuilder;
return useFeatureGroup;
}
public ScoreFunctionBuilder getPersonalizedScoreFunctionBuilder(Map<String, String> paramMap) {
public void addPersonalizedFieldValueFactor(FunctionScoreQueryBuilder functionScoreQueryBuilder, Map<String, String> paramMap) {
String pageId = this.getPageIdFromParamMap(paramMap);
float factor = getFunctionScoreFactor(pageId);
String fieldName = getFuncScoreField(pageId);
return ScoreFunctionBuilders.fieldValueFactorFunction(fieldName).factor(factor).modifier(FieldValueFactorFunction.Modifier.LOG2P)
.missing(PConsts.PRODUCT_FUNCTION_MISSING_VALUE);
FieldValueFactorFunctionBuilder fieldValueFactorFunctionBuilder = ScoreFunctionBuilders.fieldValueFactorFunction(fieldName).factor(factor)
.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);
Map<String, List<SearchFeature>> userGroupFeatures = this.getUserGroupSearchFeatures(uid, pageId);
if (userGroupFeatures == null || userGroupFeatures.isEmpty()) {
return;
}
// 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));
}
}
}
private float getMaxBoost(List<SearchFeature> searchFeatures) {
float boost = 0f;
for (SearchFeature searchFeature : searchFeatures) {
... ... @@ -186,21 +153,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;
// 对于模糊搜索, 需要把商品特征的权重得分降低, 其余的按其排序
... ...
... ... @@ -45,25 +45,76 @@ public class PromotionController {
}
}
@RequestMapping(method = RequestMethod.POST, value = "/selections")
@ResponseBody
public SearchApiResult selections(@RequestBody JSONObject param) {
try {
PromotionConditions promotionConditions = this.genPromotionConditions(param);
Map<String, String> paramMap = this.genOtherParamMap(param);
return promotionService.selectionsForApp(promotionConditions, paramMap);
} catch (Exception e) {
logger.error(e.getMessage());
return new SearchApiResult().setCode(400).setMessage("参数解析错误");
}
}
/**
* 促销聚合接口
* 促销聚合接口[for app]
*
* @param request
* @return
*/
@RequestMapping(method = RequestMethod.POST, value = "/selections")
@RequestMapping(method = RequestMethod.POST, value = "/selectionsForApp")
@ResponseBody
public SearchApiResult selections(@RequestBody JSONObject param) {
public SearchApiResult selectionsForApp(@RequestBody JSONObject param) {
try {
PromotionConditions promotionConditions = this.genPromotionConditions(param);
Map<String, String> paramMap = this.genOtherParamMap(param);
return promotionService.selectionsForApp(promotionConditions, paramMap);
} catch (Exception e) {
logger.error(e.getMessage());
return new SearchApiResult().setCode(400).setMessage("参数解析错误");
}
}
/**
* 促销聚合接口[for pc]
*
* @param request
* @return
*/
@RequestMapping(method = RequestMethod.POST, value = "/selectionsForPc")
@ResponseBody
public SearchApiResult selectionsForPc(@RequestBody JSONObject param) {
try {
PromotionConditions promotionConditions = this.genPromotionConditions(param);
Map<String, String> paramMap = this.genOtherParamMap(param);
return promotionService.selections(promotionConditions, paramMap);
return promotionService.selectionsForPc(promotionConditions, paramMap);
} catch (Exception e) {
logger.error(e.getMessage());
return new SearchApiResult().setCode(400).setMessage("参数解析错误");
}
}
/**
* 促销聚合品牌的接口
*
* @param request
* @return
*/
@RequestMapping(method = RequestMethod.POST, value = "/aggBrands")
@ResponseBody
public SearchApiResult aggBrands(@RequestBody JSONObject param) {
try {
PromotionConditions promotionConditions = this.genPromotionConditions(param);
Map<String, String> paramMap = this.genOtherParamMap(param);
return promotionService.aggPromotionBrands(promotionConditions, paramMap);
} catch (Exception e) {
logger.error(e.getMessage());
return new SearchApiResult().setCode(400).setMessage("参数解析错误");
}
}
private PromotionConditions genPromotionConditions(JSONObject param) {
try {
JSONObject jsonObject = param.getJSONObject("promotion_condition");
... ... @@ -75,16 +126,16 @@ public class PromotionController {
logger.error(e.getMessage(), e);
return null;
} finally {
//param.remove("promotion_condition");
// param.remove("promotion_condition");
}
}
private Map<String, String> genOtherParamMap(JSONObject param) {
Map<String, String> map = new HashMap<String,String>();
Map<String, String> map = new HashMap<String, String>();
for (Map.Entry<String, Object> entry : param.entrySet()) {
try {
Object value = entry.getValue();
String valueString = value==null?null:value.toString();
String valueString = value == null ? null : value.toString();
map.put(entry.getKey(), valueString);
} catch (Exception e) {
logger.error(e.getMessage(), e);
... ...
package com.yoho.search.service.restapi;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.yoho.search.service.downgrade.aop.DownGradeAble;
import com.yoho.search.service.servicenew.ISearchLikeService;
import com.yoho.search.service.utils.HttpServletRequestUtils;
import com.yoho.search.service.vo.SearchApiResult;
/**
* 找相似功能
* @author hugufei
*/
@Controller
public class SearchLikeController {
@Autowired
private ISearchLikeService searchLikeService;
@DownGradeAble(key="searchLike")
@RequestMapping(method = RequestMethod.GET, value = "/searchLike")
@ResponseBody
public SearchApiResult searchLike(HttpServletRequest request){
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return searchLikeService.searchLike(paramMap);
}
}
... ...
... ... @@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.yoho.search.service.downgrade.aop.DownGradeAble;
import com.yoho.search.service.servicenew.IDiscountService;
import com.yoho.search.service.servicenew.ISearchWithCacheService;
import com.yoho.search.service.servicenew.ISelectionsWithAdvanceService;
import com.yoho.search.service.servicenew.ISelectionsWithOutAdvanceService;
... ... @@ -29,6 +30,8 @@ public class SearchNewController {
private ISelectionsWithAdvanceService selectionsWithAdvanceService;
@Autowired
private ISelectionsWithOutAdvanceService selectionsWithOutAdvanceService;
@Autowired
private IDiscountService discountService;
/**
* 对分类进行分组查询
... ... @@ -69,7 +72,7 @@ public class SearchNewController {
@ResponseBody
public SearchApiResult discount(HttpServletRequest request) {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return searchWithCacheService.discount(paramMap);
return discountService.discount(paramMap);
}
/**
... ... @@ -109,7 +112,7 @@ public class SearchNewController {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return selectionsWithOutAdvanceService.getSelectionsForApp(paramMap);
}
/**
* 获取商品数量
*
... ...
package com.yoho.search.service.service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.EventReportEnum;
... ... @@ -12,23 +29,9 @@ import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.service.helper.SearchServiceHelper;
import com.yoho.search.service.utils.SearchRequestParams;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.aggregations.Aggregation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@Service
public class AggregationService implements ApplicationEventPublisherAware{
public class AggregationService implements ApplicationEventPublisherAware {
private static final Logger logger = LoggerFactory.getLogger(AggregationService.class);
@Autowired
... ... @@ -39,7 +42,7 @@ public class AggregationService implements ApplicationEventPublisherAware{
private SearchServiceHelper searchServiceHelper;
@Autowired
private SearchCacheService cacheService;
private ApplicationEventPublisher publisher;
@Override
... ... @@ -60,14 +63,26 @@ public class AggregationService implements ApplicationEventPublisherAware{
}
private JSONObject getAggNameAndResponse(IAggregation aggregation, SearchParam searchParam, Map<String, String> paramMap, String filterParamName) throws Exception {
return getAggNameAndResponseWithMustFilter(aggregation, searchParam, null, paramMap, filterParamName);
}
private JSONObject getAggNameAndResponseWithMustFilter(IAggregation aggregation, SearchParam searchParam, QueryBuilder fiter, Map<String, String> paramMap,
String filterParamName) throws Exception {
try {
searchParam.setAggregationBuilders(Arrays.asList(aggregation.getBuilder()));
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
if (fiter != null) {
boolFilter.must(boolFilter);
}
// 如果 需要去除filterParamName的参数去聚合
BoolQueryBuilder boolQueryBuilder = null;
if (StringUtils.isNotBlank(filterParamName) && paramMap.containsKey(filterParamName) && StringUtils.isNotBlank(paramMap.get(filterParamName))) {
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, filterParamName));
boolQueryBuilder = searchServiceHelper.constructFilterBuilder(paramMap, filterParamName);
} else {
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
boolQueryBuilder = searchServiceHelper.constructFilterBuilder(paramMap, null);
}
searchParam.setFiter(boolFilter.must(boolQueryBuilder));
SearchParam searchParamClone = searchParam.clone();
// 这里会进行 聚合 结果 值 的 反序列化 ,可能得不到预定的值
JSONObject cacheObject = cacheService.getJSONObjectFromCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParamClone);
... ... @@ -84,8 +99,8 @@ public class AggregationService implements ApplicationEventPublisherAware{
} catch (Exception e) {
logger.error(e.getMessage());
publisher.publishEvent(new SearchEvent(EventReportEnum.AGGREGATIONSERVICE_GETAGGNAMEANDRESPONSE.getEventName(),
EventReportEnum.AGGREGATIONSERVICE_GETAGGNAMEANDRESPONSE.getFunctionName(),
EventReportEnum.AGGREGATIONSERVICE_GETAGGNAMEANDRESPONSE.getMoudleName(),"exception",IgnoreSomeException.filterSomeException(e),null));
EventReportEnum.AGGREGATIONSERVICE_GETAGGNAMEANDRESPONSE.getFunctionName(), EventReportEnum.AGGREGATIONSERVICE_GETAGGNAMEANDRESPONSE.getMoudleName(),
"exception", IgnoreSomeException.filterSomeException(e), null));
return null;
}
}
... ... @@ -100,22 +115,28 @@ public class AggregationService implements ApplicationEventPublisherAware{
* @return
* @throws Exception
*/
private JSONObject getAggNameAndResponseWithOutCache(IAggregation aggregation, SearchParam searchParam, Map<String, String> paramMap, String filterParamName) throws Exception {
private JSONObject getAggNameAndResponseWithOutCache(IAggregation aggregation, SearchParam searchParam, QueryBuilder mustFiter, Map<String, String> paramMap,
String filterParamName) throws Exception {
try {
searchParam.setAggregationBuilders(Arrays.asList(aggregation.getBuilder()));
// 如果 需要去除filterParamName的参数去聚合
BoolQueryBuilder boolQueryBuilder = null;
if (StringUtils.isNotBlank(filterParamName) && paramMap.containsKey(filterParamName) && StringUtils.isNotBlank(paramMap.get(filterParamName))) {
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, filterParamName));
boolQueryBuilder = searchServiceHelper.constructFilterBuilder(paramMap, filterParamName);
} else {
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
boolQueryBuilder = searchServiceHelper.constructFilterBuilder(paramMap, null);
}
if (mustFiter != null) {
boolQueryBuilder.must(mustFiter);
}
searchParam.setFiter(boolQueryBuilder);
Map<String, Aggregation> aggMaps = this.doSearchForAggregation(searchParam, paramMap);
return aggregation.getAggNameAndResponse(aggMaps);
} catch (Exception e) {
logger.error(e.getMessage());
publisher.publishEvent(new SearchEvent(EventReportEnum.AGGREGATIONSERVICE_GETAGGNAMEANDRESPONSEWITHOUTCACHE.getEventName(),
EventReportEnum.AGGREGATIONSERVICE_GETAGGNAMEANDRESPONSEWITHOUTCACHE.getFunctionName(),
EventReportEnum.AGGREGATIONSERVICE_GETAGGNAMEANDRESPONSEWITHOUTCACHE.getMoudleName(),"exception",IgnoreSomeException.filterSomeException(e),null));
EventReportEnum.AGGREGATIONSERVICE_GETAGGNAMEANDRESPONSEWITHOUTCACHE.getFunctionName(), EventReportEnum.AGGREGATIONSERVICE_GETAGGNAMEANDRESPONSEWITHOUTCACHE
.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return null;
}
}
... ... @@ -145,7 +166,7 @@ public class AggregationService implements ApplicationEventPublisherAware{
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_GENDER : null;
return this.getAggNameAndResponse(aggregation, searchParam, paramMap, filterParamName);
}
/**
* 获取性别层面的聚合结果
*
... ... @@ -215,7 +236,7 @@ public class AggregationService implements ApplicationEventPublisherAware{
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_BRAND : null;
return this.getAggNameAndResponse(brandAggregation, searchParam, paramMap, filterParamName);
}
/**
* 获取品牌层面的聚合结果[不适用缓存]
*
... ... @@ -224,12 +245,13 @@ public class AggregationService implements ApplicationEventPublisherAware{
* @return
* @throws Exception
*/
public JSONObject getBrandAggregationResultWithOutCache(SearchParam searchParam, Map<String, String> paramMap, boolean needPreAggregation) throws Exception {
public JSONObject getBrandAggregationResultWithOutCache(SearchParam searchParam, Map<String, String> paramMap, QueryBuilder mustFiter, boolean needPreAggregation)
throws Exception {
IAggregation brandAggregation = aggregationFactoryService.getBrandAggregation(paramMap);
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_BRAND : null;
return this.getAggNameAndResponseWithOutCache(brandAggregation, searchParam, paramMap, filterParamName);
return this.getAggNameAndResponseWithOutCache(brandAggregation, searchParam, mustFiter, paramMap, filterParamName);
}
/**
* 获取规则层面的聚合结果
*
... ... @@ -241,7 +263,7 @@ public class AggregationService implements ApplicationEventPublisherAware{
public JSONObject getStandardAggregationResult(SearchParam searchParam, Map<String, String> paramMap) throws Exception {
IAggregation standardAggregation = aggregationFactoryService.getStandardAggregation(paramMap);
if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_PARAMETPERNUM)) {
return this.getAggNameAndResponseWithOutCache(standardAggregation, searchParam, paramMap, null);
return this.getAggNameAndResponseWithOutCache(standardAggregation, searchParam, null, paramMap, null);
}
return this.getAggNameAndResponse(standardAggregation, searchParam, paramMap, null);
}
... ... @@ -287,7 +309,7 @@ public class AggregationService implements ApplicationEventPublisherAware{
String filterParamName = needPreAggregation ? SearchRequestParams.PARAM_SEARCH_ISLIMITED : null;
return this.getAggNameAndResponse(isLimitedAggregation, searchParam, paramMap, filterParamName);
}
/**
* 获取是否特供的聚合结果
*
... ...
... ... @@ -28,6 +28,15 @@ public class SearchDynamicConfigService {
public boolean openPersonalized() {
return configReader.getBoolean("search.degrade.open.personalized", true);
}
/**
* 是否开启个性化
*
* @return
*/
public int userPersonalizedMaxCount() {
return configReader.getInt("search.degrade.personalized.maxcount", 20);
}
/**
* 品牌降分或过滤是否打开
... ... @@ -46,7 +55,7 @@ public class SearchDynamicConfigService {
public boolean containglobal() {
return configReader.getBoolean("search.degrade.open.containglobal", true);
}
/**
* 是否返回变价计划
*
... ...
... ... @@ -24,29 +24,21 @@ public class FunctionScoreSearchHelper {
@Autowired
private SearchDynamicConfigService dynamicConfig;
private static float globalWeight = 0.50f;
private static float brandTotalMatchWeight = 5f;
static float globalWeight = 0.50f;
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)) {
functionScoreQueryBuilder.add(personalizedSearch.getPersonalizedScoreFunctionBuilder(paramMap));
personalizedSearch.addPersonalizedUserFetureFactor(functionScoreQueryBuilder, paramMap);
personalizedSearch.addPersonalizedFieldValueFactor(functionScoreQueryBuilder, paramMap);
}
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));
}
... ...
... ... @@ -2,6 +2,8 @@ package com.yoho.search.service.servicenew;
import java.util.Map;
import org.elasticsearch.index.query.BoolQueryBuilder;
import com.yoho.search.service.vo.SearchApiResult;
public interface IBrandService {
... ... @@ -13,6 +15,14 @@ public interface IBrandService {
* @return
*/
public SearchApiResult aggBrand(Map<String, String> paramMap);
/**
* 获取品牌的聚合结果[使用本地缓存]
*
* @param paramMap
* @return
*/
public SearchApiResult aggBrand(Map<String, String> paramMap,BoolQueryBuilder mustFilter);
/**
* 按品牌前缀名获取品牌列表[使用本地缓存]
... ...
package com.yoho.search.service.servicenew;
import java.util.Map;
import org.elasticsearch.index.query.BoolQueryBuilder;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.service.vo.SearchApiResult;
public interface IDiscountService {
/**
* 获取折扣以及商品数量
*
* @param paramMap
* @return
*/
public SearchApiResult discount(Map<String, String> paramMap);
/**
* 获取折扣以及商品数量
*
* @param paramMap
* @param boolQueryBuilder
* @return
*/
public JSONObject discount(Map<String, String> paramMap, BoolQueryBuilder boolQueryBuilder);
}
... ...
... ... @@ -5,7 +5,7 @@ import java.util.Map;
import com.yoho.search.service.vo.PromotionConditions;
import com.yoho.search.service.vo.SearchApiResult;
public interface IPromotionService{
public interface IPromotionService {
/**
* 获取促销列表的接口
... ... @@ -13,14 +13,31 @@ public interface IPromotionService{
* @param paramMap
* @return
*/
public SearchApiResult list(PromotionConditions promotionConditions,Map<String,String> paramMap) throws Exception ;
public SearchApiResult list(PromotionConditions promotionConditions, Map<String, String> paramMap) throws Exception;
/**
* 获取促销聚合的接口
* 获取促销聚合的接口[for app]
*
* @param paramMap
* @return
*/
public SearchApiResult selections(PromotionConditions promotionConditions,Map<String,String> paramMap) throws Exception ;
public SearchApiResult selectionsForApp(PromotionConditions promotionConditions, Map<String, String> paramMap) throws Exception;
/**
* 获取促销聚合的接口[for pc]
*
* @param paramMap
* @return
*/
public SearchApiResult selectionsForPc(PromotionConditions promotionConditions, Map<String, String> paramMap) throws Exception;
/**
* 聚合促销相关的所有品牌
*
* @param promotionConditions
* @param paramMap
* @return
*/
public SearchApiResult aggPromotionBrands(PromotionConditions promotionConditions, Map<String, String> paramMap) throws Exception;
}
... ...
package com.yoho.search.service.servicenew;
import java.util.Map;
import com.yoho.search.service.vo.SearchApiResult;
public interface ISearchLikeService {
/**
* 找相似功能开发
*
* @param paramMap
* @return
*/
public SearchApiResult searchLike(Map<String, String> paramMap);
}
... ...
... ... @@ -2,10 +2,28 @@ package com.yoho.search.service.servicenew;
import java.util.Map;
import org.elasticsearch.index.query.BoolQueryBuilder;
import com.alibaba.fastjson.JSONArray;
import com.yoho.search.service.vo.SearchApiResult;
public interface ISearchSortGroupService {
/**
* 聚合品类
* @param paramMap
* @return
*/
public SearchApiResult sortGroup(Map<String, String> paramMap);
/**
* 聚合品类
* @param paramMap
* @param boolQueryBuilder
* @return
*/
public JSONArray sortGroup(Map<String, String> paramMap,BoolQueryBuilder boolQueryBuilder);
}
... ...
... ... @@ -15,14 +15,6 @@ public interface ISearchWithCacheService {
public SearchApiResult recent(Map<String, String> paramMap);
/**
* 获取折扣以及商品数量
*
* @param paramMap
* @return
*/
public SearchApiResult discount(Map<String, String> paramMap);
/**
* 获取商品总数
*
* @param paramMap
... ...
... ... @@ -2,6 +2,8 @@ package com.yoho.search.service.servicenew;
import java.util.Map;
import org.elasticsearch.index.query.BoolQueryBuilder;
import com.yoho.search.service.vo.SearchApiResult;
public interface ISelectionsWithAdvanceService {
... ... @@ -22,5 +24,14 @@ public interface ISelectionsWithAdvanceService {
*/
public SearchApiResult getSelectionsForBreakSize(Map<String, String> paramMap);
/**
* 获取提前聚合的结果
* @param paramMap
* @param boolQueryBuilder
* @return
* @throws Exception
*/
public SearchApiResult getSelectionsWithAdvance(Map<String, String> paramMap, BoolQueryBuilder boolQueryBuilder) throws Exception;
}
... ...
... ... @@ -14,6 +14,7 @@ import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
... ... @@ -85,9 +86,24 @@ public class BrandServiceImpl implements IBrandService, ApplicationEventPublishe
public SearchApiResult aggBrand(Map<String, String> paramMap) {
try {
logger.info("[func=aggBrand][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
return this.aggBrand(paramMap, null);
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult("aggBrand", paramMap, e);
}
}
@Override
public SearchApiResult aggBrand(Map<String, String> paramMap, BoolQueryBuilder mustFilter) {
try {
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
BoolQueryBuilder filter = searchServiceHelper.constructFilterBuilder(paramMap, null);
if (mustFilter != null) {
filter.must(mustFilter);
}
searchParam.setFiter(filter);
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
// 1、从缓存中获取
... ... @@ -98,7 +114,7 @@ public class BrandServiceImpl implements IBrandService, ApplicationEventPublishe
return new SearchApiResult().setData(cacheJSONArray);
}
// 2、从ES中获取
JSONObject jsonObject = aggregationService.getBrandAggregationResultWithOutCache(searchParam, paramMap, true);
JSONObject jsonObject = aggregationService.getBrandAggregationResultWithOutCache(searchParam, paramMap, mustFilter, true);
if (jsonObject == null) {
return new SearchApiResult().setData(500).setMessage("exception");
}
... ... @@ -108,7 +124,6 @@ public class BrandServiceImpl implements IBrandService, ApplicationEventPublishe
searchCacheService.addJSONArrayToCache(brandCacheEnum, indexName, searchParamClone, brandJSONArray);
}
return new SearchApiResult().setData(brandJSONArray);
} catch (Exception e) {
return SearchApiResultUtils.errorSearchApiResult("aggBrand", paramMap, e);
}
... ...
package com.yoho.search.service.servicenew.impl;
import java.util.Arrays;
import java.util.Map;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.core.es.agg.IAggregation;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.core.es.utils.IgnoreSomeException;
import com.yoho.search.service.aggregations.AggInterface;
import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.service.SearchCacheService;
import com.yoho.search.service.service.SearchCommonService;
import com.yoho.search.service.service.helper.SearchCommonHelper;
import com.yoho.search.service.service.helper.SearchServiceHelper;
import com.yoho.search.service.service.helper.SearchSortHelper;
import com.yoho.search.service.servicenew.IDiscountService;
import com.yoho.search.service.servicenew.IProductIndexService;
import com.yoho.search.service.servicenew.ISelectionsWithAdvanceService;
import com.yoho.search.service.servicenew.IShopsService;
import com.yoho.search.service.utils.SearchApiResultUtils;
import com.yoho.search.service.vo.SearchApiResult;
@Service
public class DiscountServiceImpl implements IDiscountService, ApplicationEventPublisherAware {
private static final Logger logger = LoggerFactory.getLogger(DiscountServiceImpl.class);
@Autowired
private SearchSortHelper searchSortHelper;
@Autowired
private SearchCommonHelper searchCommonHelper;
@Autowired
private SearchServiceHelper searchServiceHelper;
@Autowired
private AggregationFactoryService aggregationFactoryService;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchCacheService searchCacheService;
@Autowired
private SearchAfterCacheService searchAfterCacheService;
@Autowired
private IProductIndexService productIndexService;
@Autowired
private ISelectionsWithAdvanceService selectionsWithAdvanceService;
@Autowired
private IShopsService shopsService;
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
@Override
public SearchApiResult discount(Map<String, String> paramMap) {
try {
logger.info("[func=discount][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 构造查询参数
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
// 按1-3,4-6,7-10折的规则进行聚合[按区间聚合]
IAggregation discountAggregation = aggregationFactoryService.getSubAggregationByType(AggInterface.DISCOUNT, null);
searchParam.setAggregationBuilders(Arrays.asList(discountAggregation.getBuilder()));
searchParam.setSize(0);
// 构造返回结果
SearchApiResult searchApiResult = new SearchApiResult().setMessage("discount List.");
// 先从缓存中获取,如果能取到,则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (cacheObject != null) {
Object result = searchAfterCacheService.dealDiscountCacheObject(cacheObject);
searchApiResult.setData(result);
return searchApiResult;
}
// es检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null) {
return searchApiResult.setData("");
}
Object discountAggResult = discountAggregation.getAggregationResponseMap(searchResult.getAggMaps());
if (discountAggResult == null) {
return searchApiResult.setData("");
}
JSONObject discountObject = new JSONObject();
discountObject.put("discount", discountAggResult);
searchCacheService.addJSONObjectToCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam, discountObject);
return searchApiResult.setData(discountObject);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getEventName(), EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("discount", paramMap, e);
}
}
@Override
public JSONObject discount(Map<String, String> paramMap, BoolQueryBuilder boolQueryBuilder) {
try {
logger.info("[func=discount][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 构造查询参数
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
searchParam.setFiter(boolQueryBuilder);
// 按1-3,4-6,7-10折的规则进行聚合[按区间聚合]
IAggregation discountAggregation = aggregationFactoryService.getSubAggregationByType(AggInterface.DISCOUNT, null);
searchParam.setAggregationBuilders(Arrays.asList(discountAggregation.getBuilder()));
searchParam.setSize(0);
// 先从缓存中获取,如果能取到,则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (cacheObject != null) {
return cacheObject.getJSONObject("discount");
}
// es检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null) {
return null;
}
Object discountAggResult = discountAggregation.getAggregationResponseMap(searchResult.getAggMaps());
if (discountAggResult == null) {
return null;
}
JSONObject discountObject = new JSONObject();
discountObject.put("discount", discountAggResult);
searchCacheService.addJSONObjectToCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam, discountObject);
return discountObject.getJSONObject("discount");
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getEventName(), EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return null;
}
}
}
... ...
... ... @@ -14,6 +14,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.base.utils.ConvertUtils;
import com.yoho.search.base.utils.ISearchConstants;
... ... @@ -26,7 +27,11 @@ import com.yoho.search.service.service.SearchCacheService;
import com.yoho.search.service.service.SearchCommonService;
import com.yoho.search.service.service.helper.SearchServiceHelper;
import com.yoho.search.service.service.helper.SearchSortHelper;
import com.yoho.search.service.servicenew.IBrandService;
import com.yoho.search.service.servicenew.IDiscountService;
import com.yoho.search.service.servicenew.IPromotionService;
import com.yoho.search.service.servicenew.ISearchSortGroupService;
import com.yoho.search.service.servicenew.ISelectionsWithAdvanceService;
import com.yoho.search.service.servicenew.ISelectionsWithOutAdvanceService;
import com.yoho.search.service.utils.HttpServletRequestUtils;
import com.yoho.search.service.vo.PromotionConditions;
... ... @@ -38,6 +43,8 @@ public class PromotionServiceImpl implements IPromotionService {
private static Logger CACHE_MATCH_REQUEST = LoggerFactory.getLogger("CACHE_MATCH_REQUEST");
private static Logger logger = LoggerFactory.getLogger(PromotionServiceImpl.class);
@Autowired
private SearchServiceHelper searchServiceHelper;
@Autowired
... ... @@ -52,6 +59,14 @@ public class PromotionServiceImpl implements IPromotionService {
private SearchCacheService searchCacheService;
@Autowired
private SearchAfterCacheService searchAfterCacheService;
@Autowired
private ISelectionsWithAdvanceService selectionsWithAdvanceService;
@Autowired
private IBrandService brandService;
@Autowired
private ISearchSortGroupService searchSortGroupService;
@Autowired
private IDiscountService discountService;
private BoolQueryBuilder genConditionFilter(PromotionParam param, boolean isAnd) {
BoolQueryBuilder conditionFilter = QueryBuilders.boolQuery();
... ... @@ -152,9 +167,9 @@ public class PromotionServiceImpl implements IPromotionService {
*
* @return
*/
private BoolQueryBuilder getBoolQueryBuilderByPromotion(PromotionConditions promotionConditions, BoolQueryBuilder boolQueryBuilder) {
public BoolQueryBuilder getMustFilterByPromotion(PromotionConditions promotionConditions) {
if (promotionConditions == null) {
return boolQueryBuilder;
return null;
}
// 生成每种condition的filter列表
List<BoolQueryBuilder> conditionsFilter = new ArrayList<BoolQueryBuilder>();
... ... @@ -175,9 +190,7 @@ public class PromotionServiceImpl implements IPromotionService {
allBuilder.should(conditionFilter);
}
}
// 将促销条件的filter加到外面的filter[外边的条件必须满足]
boolQueryBuilder.must(allBuilder);
return boolQueryBuilder;
return allBuilder;
}
@Override
... ... @@ -187,7 +200,10 @@ public class PromotionServiceImpl implements IPromotionService {
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
// 2、设置过滤条件
BoolQueryBuilder boolQueryBuilder = searchServiceHelper.constructFilterBuilder(paramMap, null);
boolQueryBuilder = this.getBoolQueryBuilderByPromotion(promotionConditions, boolQueryBuilder);
BoolQueryBuilder mustFilterByPromotion = this.getMustFilterByPromotion(promotionConditions);
if (mustFilterByPromotion != null) {
boolQueryBuilder.must(mustFilterByPromotion);
}
searchParam.setFiter(boolQueryBuilder);
// 3、设置聚合条件
searchParam.setAggregationBuilders(null);
... ... @@ -241,13 +257,16 @@ public class PromotionServiceImpl implements IPromotionService {
}
@Override
public SearchApiResult selections(PromotionConditions promotionConditions, Map<String, String> paramMap) throws Exception {
public SearchApiResult selectionsForApp(PromotionConditions promotionConditions, Map<String, String> paramMap) throws Exception {
SearchParam searchParam = new SearchParam();
// 1、设置查询条件
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
// 2、设置过滤条件
BoolQueryBuilder boolQueryBuilder = searchServiceHelper.constructFilterBuilder(paramMap, null);
boolQueryBuilder = this.getBoolQueryBuilderByPromotion(promotionConditions, boolQueryBuilder);
BoolQueryBuilder mustFilterByPromotion = this.getMustFilterByPromotion(promotionConditions);
if (mustFilterByPromotion != null) {
boolQueryBuilder.must(mustFilterByPromotion);
}
searchParam.setFiter(boolQueryBuilder);
// 3、构造聚合条件【7种】
List<AbstractAggregationBuilder> aggregationBuilders = new ArrayList<AbstractAggregationBuilder>();
... ... @@ -260,6 +279,7 @@ public class PromotionServiceImpl implements IPromotionService {
// 3.3加上品类聚合场景
IAggregation sortGroupAggregation = aggregationFactoryService.getSortGroupAggregation(paramMap);
aggregationBuilders.add(sortGroupAggregation.getBuilder());
// 4、设置分页参数
searchParam.setPage(1);
searchParam.setOffset(0);
... ... @@ -303,5 +323,38 @@ public class PromotionServiceImpl implements IPromotionService {
searchCacheService.addJSONObjectToCache(productIndexName, searchParam, result);
return new SearchApiResult().setData(result);
}
@Override
public SearchApiResult selectionsForPc(PromotionConditions promotionConditions, Map<String, String> paramMap) throws Exception {
// 1、构造过滤条件
BoolQueryBuilder boolQueryBuilder = searchServiceHelper.constructFilterBuilder(paramMap, null);
BoolQueryBuilder mustFilterByPromotion = this.getMustFilterByPromotion(promotionConditions);
if (mustFilterByPromotion != null) {
boolQueryBuilder.must(mustFilterByPromotion);
}
// 2、调通用的PC聚合逻辑
SearchApiResult apiResult = selectionsWithAdvanceService.getSelectionsWithAdvance(paramMap, boolQueryBuilder);
if (apiResult == null || apiResult.getData() == null) {
return apiResult;
}
JSONObject result = (JSONObject) apiResult.getData();
// 3、加入品类聚合结果
JSONArray jsonArray = searchSortGroupService.sortGroup(paramMap, boolQueryBuilder);
result.put("sort", jsonArray);
// 4、加入折扣聚合结果
JSONObject discount = discountService.discount(paramMap, boolQueryBuilder);
result.put("dicount", discount);
return new SearchApiResult().setData(result);
}
@Override
public SearchApiResult aggPromotionBrands(PromotionConditions promotionConditions, Map<String, String> paramMap) throws Exception {
logger.info("[func=aggPromotionBrands][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 1、设置必须满足的过滤条件
BoolQueryBuilder mustFilterByPromotion = this.getMustFilterByPromotion(promotionConditions);
// 2、调聚合品牌的方法
SearchApiResult searchApiResult = brandService.aggBrand(paramMap, mustFilterByPromotion);
return searchApiResult;
}
}
... ...
package com.yoho.search.service.servicenew.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.service.cache.CacheEnum;
import com.yoho.search.service.service.SearchCacheService;
import com.yoho.search.service.service.SearchCommonService;
import com.yoho.search.service.service.helper.SearchCommonHelper;
import com.yoho.search.service.service.helper.SearchServiceHelper;
import com.yoho.search.service.service.helper.SearchSortHelper;
import com.yoho.search.service.servicenew.ISearchLikeService;
import com.yoho.search.service.utils.SearchRequestParams;
import com.yoho.search.service.vo.SearchApiResult;
@Service
public class SearchLikeServiceImpl implements ISearchLikeService {
@Autowired
private SearchCommonHelper searchCommonHelper;
@Autowired
private SearchCommonService searchCommonService;
@Autowired
private SearchServiceHelper searchServiceHelper;
@Autowired
private SearchSortHelper searchSortHelper;
@Autowired
private SearchCacheService searchCacheService;
@Override
public SearchApiResult searchLike(Map<String, String> paramMap) {
// 1、获取参数
String productSkn = paramMap.get(SearchRequestParams.PARAM_SYNC_SKN);
if (StringUtils.isBlank(productSkn)) {
return new SearchApiResult().setCode(400).setMessage("请输入SKN");
}
// 2、获取当前查询的SKN的基本信息
Map<String, Object> productInfo = this.getProductSknInfo(productSkn);
if (productInfo == null) {
return new SearchApiResult().setCode(400).setMessage("SKN不存在");
}
// 3、构建找相似的参数
int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
int page = StringUtils.isBlank(paramMap.get("page")) ? 1 : Integer.parseInt(paramMap.get("page"));
if (page < 1 || pageSize < 0) {
return new SearchApiResult().setCode(400).setMessage("分页参数不合法");
}
if (pageSize > 300) {
pageSize = 300;
}
// 用来做加分
int brand_id = (int) productInfo.get("brand_id");
// 用来做过滤
int max_sort_id = (int) productInfo.get("max_sort_id");
int middle_sort_id = (int) productInfo.get("middle_sort_id");
int small_sort_id = (int) productInfo.get("small_sort_id");
String gender = (String) productInfo.get("gender");
// 用来做模糊搜索
String product_name = (String) productInfo.get("product_name");
String brand_name = (String) productInfo.get("brand_name");
SearchParam searchParam = new SearchParam();
// 2、构建多字段匹配【keyword需要有一个默认的查询字段以及权重设置,就可以拼接成一个sql】
MultiMatchQueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(product_name + brand_name);
MultiMatchQueryBuilder.Type multiMatchQueryBuilderType = searchCommonHelper.getMultiMatchQueryBuilderType();
if (multiMatchQueryBuilderType != null) {
queryBuilder.type(multiMatchQueryBuilderType);
}
List<String> fields = ISearchConstants.SEARCH_DEFAULT_FIELD;
for (String field : fields) {
String[] fieldBoost = field.split("\\^");
if (fieldBoost.length == 2) {
queryBuilder.field(fieldBoost[0], Float.parseFloat(fieldBoost[1]));
} else if (fieldBoost.length == 1) {
queryBuilder.field(fieldBoost[0]);
}
}
queryBuilder.minimumShouldMatch("30%");
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder);
functionScoreQueryBuilder.add(QueryBuilders.termQuery("brandId", brand_id), ScoreFunctionBuilders.weightFactorFunction(1.1f));
searchParam.setQuery(functionScoreQueryBuilder);
// 3、设置过滤条件
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
boolFilter.must(QueryBuilders.termQuery("status", 1));
boolFilter.must(QueryBuilders.termQuery("gender", gender));
boolFilter.must(QueryBuilders.termQuery("isOutlets", 2));
boolFilter.must(QueryBuilders.termQuery("attribute", 1));
boolFilter.must(QueryBuilders.rangeQuery("storageNum").gte(1));
BoolQueryBuilder sortFilter = QueryBuilders.boolQuery();
sortFilter.should(QueryBuilders.termQuery("maxSortId", max_sort_id));
sortFilter.should(QueryBuilders.termQuery("middleSortId", middle_sort_id));
sortFilter.should(QueryBuilders.termQuery("smallSortId", small_sort_id));
boolFilter.must(sortFilter);
boolFilter.mustNot(QueryBuilders.termQuery("productSkn", productSkn));
boolFilter.mustNot(QueryBuilders.termsQuery("isSeckill", "Y"));
boolFilter.mustNot(QueryBuilders.termsQuery("isGlobal", "Y"));
searchParam.setFiter(boolFilter);
// 4、设置排序规则[支持持按打分排序]
List<SortBuilder>sortBuilders = new ArrayList<SortBuilder>();
sortBuilders.add(SortBuilders.fieldSort("_score").order(SortOrder.DESC));
searchParam.setSortBuilders(sortBuilders);
// 5、设置分页
searchParam.setPage(page);
searchParam.setOffset((page - 1) * pageSize);
searchParam.setSize(pageSize);
String productIndexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
CacheEnum cacheEnum = CacheEnum.EHCACHE;
JSONObject dataMap = searchCacheService.getJSONObjectFromCache(cacheEnum,productIndexName, searchParam);
if(dataMap!=null){
return new SearchApiResult().setData(dataMap);
}
// 6、执行搜索
SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
SearchApiResult searchApiResult = new SearchApiResult();
dataMap = new JSONObject();
long total = searchResult.getTotal();
if(total>300){
total = 300;
}
dataMap.put("total", total);
dataMap.put("page", page);
dataMap.put("page_size", pageSize);
dataMap.put("page_total", this.getPageTotal(total, pageSize));
dataMap.put("product_info", productInfo);
dataMap.put("product_list", searchServiceHelper.getProductMapList(searchResult.getResultList()));
searchCacheService.addJSONObjectToCache(cacheEnum, productIndexName, searchParam, dataMap);
return searchApiResult.setData(dataMap);
}
private long getPageTotal(long total,int pageSize){
if(pageSize<=0){
return total;
}
if(total % pageSize==0){
return total / pageSize;
}else{
return total / pageSize + 1;
}
}
private JSONObject getProductSknInfo(String productSkn) {
SearchParam searchParam = new SearchParam();
searchParam.setQuery(QueryBuilders.matchAllQuery());
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
boolFilter.must(QueryBuilders.termsQuery("productSkn", productSkn));
boolFilter.mustNot(QueryBuilders.termsQuery("isGlobal", "Y"));
searchParam.setFiter(boolFilter);
searchParam.setAggregationBuilders(null);
searchParam.setPage(0);
searchParam.setOffset(0);
searchParam.setSize(1);
String productIndexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
JSONObject jsonObject = searchCacheService.getJSONObjectFromCache(productIndexName, searchParam);
if(jsonObject!=null){
return jsonObject;
}
SearchResult searchResult = searchCommonService.doSearch(productIndexName, searchParam);
if (searchResult == null) {
return null;
}
List<Map<String, Object>> productLists = searchResult.getResultList();
if (productLists == null || productLists.isEmpty()) {
return null;
}
Map<String, Object> productInfoMap = searchServiceHelper.getProductMap(productLists.get(0));
if (productInfoMap == null) {
return null;
}
jsonObject = new JSONObject();
jsonObject.putAll(productInfoMap);
searchCacheService.addJSONObjectToCache(productIndexName, searchParam, jsonObject);
return jsonObject;
}
}
... ...
... ... @@ -12,6 +12,7 @@ import java.util.Map;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation;
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation.Bucket;
... ... @@ -23,10 +24,12 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.error.event.SearchEvent;
import com.yoho.search.base.utils.EventReportEnum;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.core.es.agg.IAggregation;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.core.es.utils.IgnoreSomeException;
... ... @@ -45,9 +48,9 @@ import com.yoho.search.service.vo.SearchApiResult;
public class SearchSortGroupService implements ISearchSortGroupService, ApplicationEventPublisherAware {
private static Logger logger = LoggerFactory.getLogger(SearchSortGroupService.class);
private static Logger CACHE_MATCH_REQUEST = LoggerFactory.getLogger("CACHE_MATCH_REQUEST");
@Autowired
private SearchCommonHelper searchCommonHelper;
@Autowired
... ... @@ -58,7 +61,6 @@ public class SearchSortGroupService implements ISearchSortGroupService, Applicat
private AggregationFactoryService aggregationFactoryService;
@Autowired
private SearchCacheService searchCacheService;
ApplicationEventPublisher publisher;
@Override
... ... @@ -94,7 +96,7 @@ public class SearchSortGroupService implements ISearchSortGroupService, Applicat
boolFilter.must(QueryBuilders.termQuery("gender", genders));
}
// 如果contain_global!=Y,则过滤掉全球购的商品[全球购商品融合需求]
if (!searchCommonHelper.containGlobal(paramMap)){
if (!searchCommonHelper.containGlobal(paramMap)) {
boolFilter.mustNot(QueryBuilders.termQuery("isGlobal", "Y"));
}
if (boolFilter.hasClauses()) {
... ... @@ -161,7 +163,7 @@ public class SearchSortGroupService implements ISearchSortGroupService, Applicat
return SearchApiResultUtils.errorSearchApiResult("sortGroup", paramMap, e);
}
}
/**
* 制作品类报文
* */
... ... @@ -235,4 +237,55 @@ public class SearchSortGroupService implements ISearchSortGroupService, Applicat
return sortList;
}
@Override
public JSONArray sortGroup(Map<String, String> paramMap, BoolQueryBuilder boolQueryBuilder) {
try {
long begin = System.currentTimeMillis();
logger.info("[model=SearchSortGroupService][func=sortGroup][param={}][begin={}]", paramMap.toString(), begin);
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
searchParam.setFiter(boolQueryBuilder);
// 构造聚合条件
List<AbstractAggregationBuilder> sortGroupBuilders = new ArrayList<AbstractAggregationBuilder>();
IAggregation sortGroupAggregation = aggregationFactoryService.getSortGroupAggregation(paramMap);
sortGroupBuilders.add(sortGroupAggregation.getBuilder());
searchParam.setAggregationBuilders(sortGroupBuilders);
// 设置查询结果返回字段
List<String> resultFields = new ArrayList<String>();
resultFields.add("id");
searchParam.setResultFields(resultFields);
searchParam.setSize(0);
// 先从缓存中获取,如果能取到,则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (cacheObject != null) {
return cacheObject.getJSONArray("sort");
}
// 进行检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null || !searchResult.getAggMaps().containsKey("maxAgg")) {
return new JSONArray();
}
// 获取品类聚合结果
JSONArray sortGroups = (JSONArray) sortGroupAggregation.getAggregationResponseMap(searchResult.getAggMaps());
if (sortGroups == null) {
return new JSONArray();
}
JSONObject sortResult = new JSONObject();
sortResult.put("sort", sortGroups);
searchCacheService.addJSONObjectToCache(indexName, searchParam, sortResult);
return sortGroups;
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getEventName(), EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_SORTGROUP.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return new JSONArray();
}
}
}
... ...
... ... @@ -23,17 +23,12 @@ import com.yoho.search.core.es.agg.IAggregation;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.core.es.utils.IgnoreSomeException;
import com.yoho.search.service.aggregations.AggInterface;
import com.yoho.search.service.aggregations.impls.AggregationFactoryService;
import com.yoho.search.service.service.SearchCacheService;
import com.yoho.search.service.service.SearchCommonService;
import com.yoho.search.service.service.helper.SearchCommonHelper;
import com.yoho.search.service.service.helper.SearchServiceHelper;
import com.yoho.search.service.service.helper.SearchSortHelper;
import com.yoho.search.service.servicenew.IProductIndexService;
import com.yoho.search.service.servicenew.ISearchWithCacheService;
import com.yoho.search.service.servicenew.ISelectionsWithAdvanceService;
import com.yoho.search.service.servicenew.IShopsService;
import com.yoho.search.service.utils.HttpServletRequestUtils;
import com.yoho.search.service.utils.SearchApiResultUtils;
import com.yoho.search.service.vo.SearchApiResult;
... ... @@ -46,8 +41,6 @@ public class SearchWithCacheServiceImpl implements ISearchWithCacheService, Appl
private static Logger CACHE_MATCH_REQUEST = LoggerFactory.getLogger("CACHE_MATCH_REQUEST");
@Autowired
private SearchSortHelper searchSortHelper;
@Autowired
private SearchCommonHelper searchCommonHelper;
@Autowired
private SearchServiceHelper searchServiceHelper;
... ... @@ -59,12 +52,6 @@ public class SearchWithCacheServiceImpl implements ISearchWithCacheService, Appl
private SearchCacheService searchCacheService;
@Autowired
private SearchAfterCacheService searchAfterCacheService;
@Autowired
private IProductIndexService productIndexService;
@Autowired
private ISelectionsWithAdvanceService selectionsWithAdvanceService;
@Autowired
private IShopsService shopsService;
private ApplicationEventPublisher publisher;
... ... @@ -124,54 +111,6 @@ public class SearchWithCacheServiceImpl implements ISearchWithCacheService, Appl
}
@Override
public SearchApiResult discount(Map<String, String> paramMap) {
try {
logger.info("[func=discount][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
// 构造查询参数
SearchParam searchParam = new SearchParam();
searchParam.setQuery(searchServiceHelper.constructQueryBuilder(paramMap));
searchParam.setFiter(searchServiceHelper.constructFilterBuilder(paramMap, null));
// 按1-3,4-6,7-10折的规则进行聚合[按区间聚合]
IAggregation discountAggregation = aggregationFactoryService.getSubAggregationByType(AggInterface.DISCOUNT, null);
searchParam.setAggregationBuilders(Arrays.asList(discountAggregation.getBuilder()));
searchParam.setSize(0);
// 构造返回结果
SearchApiResult searchApiResult = new SearchApiResult().setMessage("discount List.");
// 先从缓存中获取,如果能取到,则直接返回
JSONObject cacheObject = searchCacheService.getJSONObjectFromCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
if (cacheObject != null) {
Object result = searchAfterCacheService.dealDiscountCacheObject(cacheObject);
searchApiResult.setData(result);
CACHE_MATCH_REQUEST.info("match cache , url is :/discount.json?" + HttpServletRequestUtils.genParamString(paramMap));
return searchApiResult;
}
// es检索
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
if (searchResult == null || searchResult.getAggMaps() == null) {
return searchApiResult.setData("");
}
Object discountAggResult = discountAggregation.getAggregationResponseMap(searchResult.getAggMaps());
if (discountAggResult == null) {
return searchApiResult.setData("");
}
JSONObject discountObject = new JSONObject();
discountObject.put("discount", discountAggResult);
searchCacheService.addJSONObjectToCache(ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam, discountObject);
return searchApiResult.setData(discountObject);
} catch (Exception e) {
publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getEventName(), EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getFunctionName(),
EventReportEnum.SEARCHCONTROLLER_DISCOUNT.getMoudleName(), "exception", IgnoreSomeException.filterSomeException(e), null));
return SearchApiResultUtils.errorSearchApiResult("discount", paramMap, e);
}
}
@Override
public SearchApiResult productCount(Map<String, String> paramMap) {
try {
logger.info("[func=productCount][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
... ...
... ... @@ -30,7 +30,7 @@ search.index.translog.flush_threshold_ops=5000
#search
search.minimum.should.match=75%
search.operator=and
search.default.field=smallSort^1000,smallSort.smallSort_pinyin^1000,middleSort^950,middleSort.middleSort_pinyin^950,maxSort^900,maxSort.maxSort_pinyin^900,brandName^900,brandNameCn^850,brandNameCn.brandNameCn_pinyin^850,brandNameEn^800,brandDomain^800,specialSearchField^700,productName.productName_ansj^300,standardOnlyNames.standardOnlyNames_pinyin^250,standardOnlyNames.standardOnlyNames_ansj^250,productKeyword^50,brandKeyword^30,genderS^20,searchField_ansj^10,searchField,productSkn.productSkn_ansj
search.default.field=brandName.brandName_lowercase^2500,smallSort^1000,smallSort.smallSort_pinyin^1000,middleSort^950,middleSort.middleSort_pinyin^950,maxSort^900,maxSort.maxSort_pinyin^900,brandName^900,brandNameCn^850,brandNameCn.brandNameCn_pinyin^850,brandNameEn^800,brandDomain^800,specialSearchField^700,productName.productName_ansj^300,standardOnlyNames.standardOnlyNames_pinyin^250,standardOnlyNames.standardOnlyNames_ansj^250,productKeyword^50,brandKeyword^30,genderS^20,searchField_ansj^10,searchField,productSkn.productSkn_ansj
search.script.score=_score+doc['sortWeight'].value*0.003+(100-doc['breakingRate'].value)/100 * doc['salesWithDateDiff'].value/pow((now-doc['shelveTime'].value)/3600+2,1.8)
search.script.lang=groovy
... ... @@ -38,7 +38,7 @@ search.use.cache=true
search.cache.type=redisCache
search.personalized.switch=true
search.personalized.max.should=50
search.personalized.max.should=20
#search.cache.type=ehCache
tpl.adaptor.valid=true
... ...
... ... @@ -6,6 +6,9 @@ search.degrade.direct.downgrade=false
#search open personalized[true:open personalized, false:close personalized]
search.degrade.open.personalized=true
#search open personalized[true:open personalized, false:close personalized]
search.degrade.personalized.maxcount=20
#search.open.descorebrand[true:open descorebrand, false:close descorebrand]
search.degrade.open.descorebrand=true
... ...
... ... @@ -30,7 +30,7 @@ search.index.translog.flush_threshold_ops=${search.index.translog.flush_threshol
#search
search.minimum.should.match=75%
search.operator=and
search.default.field=smallSort^1000,smallSort.smallSort_pinyin^1000,middleSort^950,middleSort.middleSort_pinyin^950,maxSort^900,maxSort.maxSort_pinyin^900,brandName^900,brandNameCn^850,brandNameCn.brandNameCn_pinyin^850,brandNameEn^800,brandDomain^800,specialSearchField^700,productName.productName_ansj^300,standardOnlyNames.standardOnlyNames_pinyin^250,standardOnlyNames.standardOnlyNames_ansj^250,productKeyword^50,brandKeyword^30,genderS^20,searchField_ansj^10,searchField,productSkn.productSkn_ansj
search.default.field=brandName.brandName_lowercase^2500,smallSort^1000,smallSort.smallSort_pinyin^1000,middleSort^950,middleSort.middleSort_pinyin^950,maxSort^900,maxSort.maxSort_pinyin^900,brandName^900,brandNameCn^850,brandNameCn.brandNameCn_pinyin^850,brandNameEn^800,brandDomain^800,specialSearchField^700,productName.productName_ansj^300,standardOnlyNames.standardOnlyNames_pinyin^250,standardOnlyNames.standardOnlyNames_ansj^250,productKeyword^50,brandKeyword^30,genderS^20,searchField_ansj^10,searchField,productSkn.productSkn_ansj
search.script.score=_score+doc['sortWeight'].value*0.003+(100-doc['breakingRate'].value)/100 * doc['salesWithDateDiff'].value/pow((now-doc['shelveTime'].value)/3600+2,1.8)
search.script.lang=groovy
... ...