Authored by 胡古飞

优化个性化相关的代码

@@ -3,41 +3,124 @@ package com.yoho.search.service.personalized; @@ -3,41 +3,124 @@ package com.yoho.search.service.personalized;
3 import java.util.Collections; 3 import java.util.Collections;
4 import java.util.Comparator; 4 import java.util.Comparator;
5 import java.util.List; 5 import java.util.List;
  6 +import java.util.Map;
6 7
7 import org.apache.commons.lang.StringUtils; 8 import org.apache.commons.lang.StringUtils;
8 -import org.elasticsearch.common.lucene.search.function.CombineFunction;  
9 import org.elasticsearch.common.lucene.search.function.FieldValueFactorFunction; 9 import org.elasticsearch.common.lucene.search.function.FieldValueFactorFunction;
10 import org.elasticsearch.index.query.BoolQueryBuilder; 10 import org.elasticsearch.index.query.BoolQueryBuilder;
11 import org.elasticsearch.index.query.QueryBuilder; 11 import org.elasticsearch.index.query.QueryBuilder;
12 import org.elasticsearch.index.query.QueryBuilders; 12 import org.elasticsearch.index.query.QueryBuilders;
13 -import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder; 13 +import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder;
14 import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders; 14 import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
  15 +import org.slf4j.Logger;
  16 +import org.slf4j.LoggerFactory;
15 import org.springframework.beans.factory.annotation.Autowired; 17 import org.springframework.beans.factory.annotation.Autowired;
16 import org.springframework.stereotype.Service; 18 import org.springframework.stereotype.Service;
17 19
18 import com.yoho.search.base.utils.ISearchConstants; 20 import com.yoho.search.base.utils.ISearchConstants;
19 import com.yoho.search.core.personalized.PConsts; 21 import com.yoho.search.core.personalized.PConsts;
20 import com.yoho.search.service.personalized.model.SearchFeature; 22 import com.yoho.search.service.personalized.model.SearchFeature;
  23 +import com.yoho.search.service.service.SearchDynamicConfigService;
  24 +import com.yoho.search.service.utils.HttpServletRequestUtils;
21 25
22 @Service 26 @Service
23 public final class PersonalizedSearch { 27 public final class PersonalizedSearch {
24 28
25 - private static final float MaxUserFeatureBoost = 50;  
26 -  
27 @Autowired 29 @Autowired
28 private UserFeaturesRedis userFeatures; 30 private UserFeaturesRedis userFeatures;
  31 + @Autowired
  32 + private SearchDynamicConfigService dynamicConfig;
  33 +
  34 + private static final float MaxUserFeatureBoost = 50;
  35 + private static final Logger PERSONALIZED = LoggerFactory.getLogger("PERSONALIZED");
  36 +
  37 + // public QueryBuilder builder(QueryBuilder queryBuilder, String uid, String
  38 + // pageId) {
  39 + // QueryBuilder qBuilder = null;
  40 + // List<SearchFeature> sfRedis = userFeatures.getUserFeaturesFromRedis(uid,
  41 + // pageId);
  42 + // if (sfRedis == null || sfRedis.isEmpty()) {
  43 + // qBuilder = queryBuilder;
  44 + // } else {
  45 + // BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
  46 + // boolQueryBuilder.must(queryBuilder);
  47 + //
  48 + // List<SearchFeature> searchFeatures = null;
  49 + // // should个数超过一定数量, 按权重值desc排序, 截取数据
  50 + // if (sfRedis.size() > ISearchConstants.PERSONALIZED_SEARCH_SHOULD_MAX) {
  51 + // // 按照boost进行排序
  52 + // Collections.sort(sfRedis, new Comparator<SearchFeature>() {
  53 + // @Override
  54 + // public int compare(SearchFeature left, SearchFeature right) {
  55 + // Float fleft = Float.valueOf(left.getBoost());
  56 + // Float fright = Float.valueOf(right.getBoost());
  57 + // return fright.compareTo(fleft);
  58 + // }
  59 + // });
  60 + // searchFeatures = sfRedis.subList(0,
  61 + // ISearchConstants.PERSONALIZED_SEARCH_SHOULD_MAX);
  62 + // } else {
  63 + // searchFeatures = sfRedis;
  64 + // }
  65 + // // 获取用户最大的boost
  66 + // float maxBoost = this.getMaxBoost(searchFeatures);
  67 + // boolean isFuzzySearch = this.isFuzzySearch(pageId);
  68 + // for (SearchFeature searchFeature : searchFeatures) {
  69 + // float boost = searchFeature.getBoost();
  70 + // if (isFuzzySearch) {
  71 + // boost = getAdaptoredBoost(maxBoost, boost);
  72 + // }
  73 + // boolQueryBuilder.should(QueryBuilders.termQuery(searchFeature.getTargetParam(),
  74 + // searchFeature.getParamValues()).boost(boost));
  75 + // }
  76 + // qBuilder = boolQueryBuilder;
  77 + // }
  78 + //
  79 + // float factor = getFunctionScoreFactor(pageId);
  80 + // // new_score = old_score * log(2 + factor * page_boosts)
  81 + // String fieldName = getFuncScoreField(pageId);
  82 + // FunctionScoreQueryBuilder fsQueryBuilder = new
  83 + // FunctionScoreQueryBuilder(qBuilder);
  84 + // fsQueryBuilder.add(
  85 + // ScoreFunctionBuilders.fieldValueFactorFunction(fieldName).factor(factor).modifier(FieldValueFactorFunction.Modifier.LOG2P)
  86 + // .missing(PConsts.PRODUCT_FUNCTION_MISSING_VALUE)).boostMode(CombineFunction.MULT);
  87 + //
  88 + // return fsQueryBuilder;
  89 + // }
  90 +
  91 + private String getUidFromParamMap(Map<String, String> paramMap) {
  92 + return paramMap.get("uid");
  93 + }
  94 +
  95 + private String getPageIdFromParamMap(Map<String, String> paramMap) {
  96 + String pageId = paramMap.get("pageId");
  97 + if (StringUtils.isBlank(pageId)) {
  98 + pageId = PConsts.PAGE_ID_NEW;
  99 + }
  100 + return pageId;
  101 + }
  102 +
  103 + /**
  104 + * 针对用户特征,对用户进行加分
  105 + *
  106 + * @param queryBuilder
  107 + * @param uid
  108 + * @param pageId
  109 + * @return
  110 + */
  111 + public QueryBuilder buildPersonalizedQueryBuilder(QueryBuilder queryBuilder, Map<String, String> paramMap) {
  112 + PERSONALIZED.info("do personal search , paramString is [{}]", HttpServletRequestUtils.genParamString(paramMap));
29 113
30 - public QueryBuilder builder(QueryBuilder queryBuilder, String uid, String pageId) {  
31 - QueryBuilder qBuilder = null; 114 + // 2、获取用户信息和页面信息
  115 + String uid = this.getUidFromParamMap(paramMap);
  116 + String pageId = this.getPageIdFromParamMap(paramMap);
32 List<SearchFeature> sfRedis = userFeatures.getUserFeaturesFromRedis(uid, pageId); 117 List<SearchFeature> sfRedis = userFeatures.getUserFeaturesFromRedis(uid, pageId);
33 if (sfRedis == null || sfRedis.isEmpty()) { 118 if (sfRedis == null || sfRedis.isEmpty()) {
34 - qBuilder = queryBuilder;  
35 - } else {  
36 - BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();  
37 - boolQueryBuilder.must(queryBuilder); 119 + return queryBuilder;
  120 + }
38 121
  122 + // 3、对 用户权重进行排序,should个数超过一定数量, 按权重值desc排序, 截取数据
39 List<SearchFeature> searchFeatures = null; 123 List<SearchFeature> searchFeatures = null;
40 - // should个数超过一定数量, 按权重值desc排序, 截取数据  
41 if (sfRedis.size() > ISearchConstants.PERSONALIZED_SEARCH_SHOULD_MAX) { 124 if (sfRedis.size() > ISearchConstants.PERSONALIZED_SEARCH_SHOULD_MAX) {
42 // 按照boost进行排序 125 // 按照boost进行排序
43 Collections.sort(sfRedis, new Comparator<SearchFeature>() { 126 Collections.sort(sfRedis, new Comparator<SearchFeature>() {
@@ -52,8 +135,11 @@ public final class PersonalizedSearch { @@ -52,8 +135,11 @@ public final class PersonalizedSearch {
52 } else { 135 } else {
53 searchFeatures = sfRedis; 136 searchFeatures = sfRedis;
54 } 137 }
55 - // 获取用户最大的boost  
56 - float maxBoost = this.getMaxBoost(searchFeatures); 138 +
  139 + // 4、对用户权重 进行加分
  140 + BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
  141 + boolQueryBuilder.must(queryBuilder);
  142 + float maxBoost = this.getMaxBoost(searchFeatures);// 获取用户最大的boost,已调整boost值
57 boolean isFuzzySearch = this.isFuzzySearch(pageId); 143 boolean isFuzzySearch = this.isFuzzySearch(pageId);
58 for (SearchFeature searchFeature : searchFeatures) { 144 for (SearchFeature searchFeature : searchFeatures) {
59 float boost = searchFeature.getBoost(); 145 float boost = searchFeature.getBoost();
@@ -62,18 +148,15 @@ public final class PersonalizedSearch { @@ -62,18 +148,15 @@ public final class PersonalizedSearch {
62 } 148 }
63 boolQueryBuilder.should(QueryBuilders.termQuery(searchFeature.getTargetParam(), searchFeature.getParamValues()).boost(boost)); 149 boolQueryBuilder.should(QueryBuilders.termQuery(searchFeature.getTargetParam(), searchFeature.getParamValues()).boost(boost));
64 } 150 }
65 - qBuilder = boolQueryBuilder; 151 + return boolQueryBuilder;
66 } 152 }
67 153
  154 + public ScoreFunctionBuilder getPersonalizedScoreFunctionBuilder(Map<String, String> paramMap) {
  155 + String pageId = this.getPageIdFromParamMap(paramMap);
68 float factor = getFunctionScoreFactor(pageId); 156 float factor = getFunctionScoreFactor(pageId);
69 - // new_score = old_score * log(2 + factor * page_boosts)  
70 String fieldName = getFuncScoreField(pageId); 157 String fieldName = getFuncScoreField(pageId);
71 - FunctionScoreQueryBuilder fsQueryBuilder = new FunctionScoreQueryBuilder(qBuilder);  
72 - fsQueryBuilder.add(  
73 - ScoreFunctionBuilders.fieldValueFactorFunction(fieldName).factor(factor).modifier(FieldValueFactorFunction.Modifier.LOG2P)  
74 - .missing(PConsts.PRODUCT_FUNCTION_MISSING_VALUE)).boostMode(CombineFunction.MULT);  
75 -  
76 - return fsQueryBuilder; 158 + return ScoreFunctionBuilders.fieldValueFactorFunction(fieldName).factor(factor).modifier(FieldValueFactorFunction.Modifier.LOG2P)
  159 + .missing(PConsts.PRODUCT_FUNCTION_MISSING_VALUE);
77 } 160 }
78 161
79 private float getMaxBoost(List<SearchFeature> searchFeatures) { 162 private float getMaxBoost(List<SearchFeature> searchFeatures) {
  1 +package com.yoho.search.service.service.helper;
  2 +
  3 +import java.util.Map;
  4 +
  5 +import org.elasticsearch.common.lucene.search.function.CombineFunction;
  6 +import org.elasticsearch.index.query.QueryBuilder;
  7 +import org.elasticsearch.index.query.QueryBuilders;
  8 +import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
  9 +import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
  10 +import org.springframework.beans.factory.annotation.Autowired;
  11 +import org.springframework.stereotype.Component;
  12 +
  13 +import com.yoho.search.service.personalized.PersonalizedSearch;
  14 +import com.yoho.search.service.service.SearchDynamicConfigService;
  15 +
  16 +@Component
  17 +public class FunctionScoreSearchHelper {
  18 +
  19 + @Autowired
  20 + private SearchCommonHelper searchCommonHelper;
  21 + @Autowired
  22 + private PersonalizedSearch personalizedSearch;
  23 + @Autowired
  24 + private SearchDynamicConfigService dynamicConfig;
  25 +
  26 + private static float globalWeightFactor = 0.50f;
  27 +
  28 + public QueryBuilder buildFunctionScoreQueryBuild(QueryBuilder queryBuilder, Map<String, String> paramMap) {
  29 + //个性化时先对用户特征加分
  30 + if (searchCommonHelper.isNeedPersonalSearch(paramMap)) {
  31 + queryBuilder = personalizedSearch.buildPersonalizedQueryBuilder(queryBuilder, paramMap);
  32 + }
  33 + FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder);
  34 + if (searchCommonHelper.isNeedPersonalSearch(paramMap)) {
  35 + functionScoreQueryBuilder.add(personalizedSearch.getPersonalizedScoreFunctionBuilder(paramMap));
  36 + }
  37 + if (searchCommonHelper.containGlobal(paramMap)) {
  38 + functionScoreQueryBuilder.add(QueryBuilders.termQuery("isGlobal", "Y"), ScoreFunctionBuilders.weightFactorFunction(globalWeightFactor));
  39 + }
  40 + if (searchCommonHelper.isNeedDeScoreBrandSearch(paramMap)) {
  41 + functionScoreQueryBuilder.add(QueryBuilders.termQuery("isForbiddenSortBrand", "1"), ScoreFunctionBuilders.weightFactorFunction(0.000001f));
  42 + }
  43 + functionScoreQueryBuilder.boostMode(CombineFunction.MULT);
  44 + return functionScoreQueryBuilder;
  45 + }
  46 +
  47 +}
@@ -6,15 +6,12 @@ import org.apache.commons.lang.StringUtils; @@ -6,15 +6,12 @@ import org.apache.commons.lang.StringUtils;
6 import org.elasticsearch.index.query.BoolQueryBuilder; 6 import org.elasticsearch.index.query.BoolQueryBuilder;
7 import org.elasticsearch.index.query.MultiMatchQueryBuilder; 7 import org.elasticsearch.index.query.MultiMatchQueryBuilder;
8 import org.elasticsearch.index.query.QueryBuilders; 8 import org.elasticsearch.index.query.QueryBuilders;
9 -import org.slf4j.Logger;  
10 -import org.slf4j.LoggerFactory;  
11 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.beans.factory.annotation.Autowired;
12 import org.springframework.stereotype.Component; 10 import org.springframework.stereotype.Component;
13 11
14 import com.yoho.search.base.utils.CharUtils; 12 import com.yoho.search.base.utils.CharUtils;
15 import com.yoho.search.base.utils.ISearchConstants; 13 import com.yoho.search.base.utils.ISearchConstants;
16 import com.yoho.search.service.service.SearchDynamicConfigService; 14 import com.yoho.search.service.service.SearchDynamicConfigService;
17 -import com.yoho.search.service.utils.HttpServletRequestUtils;  
18 import com.yoho.search.service.utils.SearchRequestParams; 15 import com.yoho.search.service.utils.SearchRequestParams;
19 16
20 @Component 17 @Component
@@ -23,7 +20,28 @@ public class SearchCommonHelper { @@ -23,7 +20,28 @@ public class SearchCommonHelper {
23 @Autowired 20 @Autowired
24 private SearchDynamicConfigService dynamicConfig; 21 private SearchDynamicConfigService dynamicConfig;
25 22
26 - private static final Logger PERSONALIZED = LoggerFactory.getLogger("PERSONALIZED"); 23 + /**
  24 + * 是否需要开启个性化
  25 + *
  26 + * @param paramMap
  27 + * @return
  28 + */
  29 + public boolean isNeedPersonalSearch(Map<String, String> paramMap) {
  30 + // 从 zk中动态获取是否使用个性化
  31 + boolean openPersonalized = dynamicConfig.openPersonalized();
  32 + if (!openPersonalized) {
  33 + return false;
  34 + }
  35 + String uid = paramMap.get("uid");
  36 + if (StringUtils.isBlank(uid) || uid.equals("0")) {
  37 + return false;
  38 + }
  39 + String sortFields = paramMap.get("order");
  40 + if (!StringUtils.isBlank(sortFields)) {
  41 + return false;
  42 + }
  43 + return true;
  44 + }
27 45
28 /** 46 /**
29 * 是否需要对品牌降分 47 * 是否需要对品牌降分
@@ -56,25 +74,6 @@ public class SearchCommonHelper { @@ -56,25 +74,6 @@ public class SearchCommonHelper {
56 } 74 }
57 75
58 /** 76 /**
59 - * 是否需要开启个性化  
60 - *  
61 - * @param paramMap  
62 - * @return  
63 - */  
64 - public boolean isNeedPersonalSearch(Map<String, String> paramMap) {  
65 - // 从 zk中动态获取是否使用个性化  
66 - boolean openPersonalized = dynamicConfig.openPersonalized();  
67 - if (openPersonalized) { // 启用个性化搜索  
68 - String uid = paramMap.get("uid");  
69 - if (!StringUtils.isBlank(uid) && !uid.equals("0")) {  
70 - PERSONALIZED.info("do personal search , paramString is [{}]", HttpServletRequestUtils.genParamString(paramMap));  
71 - return true;  
72 - }  
73 - }  
74 - return false;  
75 - }  
76 -  
77 - /**  
78 * 判断搜索是否需要包含全球购 77 * 判断搜索是否需要包含全球购
79 * 78 *
80 * @param paramMap 79 * @param paramMap
@@ -54,6 +54,8 @@ public class SearchServiceHelper { @@ -54,6 +54,8 @@ public class SearchServiceHelper {
54 private SearchCommonService searchCommonService; 54 private SearchCommonService searchCommonService;
55 @Autowired 55 @Autowired
56 private DynamicSearchRuleHelper dynamicSearchRuleHelper; 56 private DynamicSearchRuleHelper dynamicSearchRuleHelper;
  57 + @Autowired
  58 + private FunctionScoreSearchHelper functionScoreSearchHelper;
57 59
58 /** 60 /**
59 * 构造关键字查询的query 61 * 构造关键字查询的query
@@ -154,10 +156,13 @@ public class SearchServiceHelper { @@ -154,10 +156,13 @@ public class SearchServiceHelper {
154 */ 156 */
155 public QueryBuilder constructQueryBuilderForProductList(Map<String, String> paramMap) { 157 public QueryBuilder constructQueryBuilderForProductList(Map<String, String> paramMap) {
156 QueryBuilder queryBuilder = this.constructQueryBuilder(paramMap); 158 QueryBuilder queryBuilder = this.constructQueryBuilder(paramMap);
157 - queryBuilder = this.buildPersonalSearch(queryBuilder, paramMap);  
158 - queryBuilder = this.buildFunctionScoreQueryBuild(queryBuilder, paramMap); 159 + queryBuilder = functionScoreSearchHelper.buildFunctionScoreQueryBuild(queryBuilder, paramMap);
159 return queryBuilder; 160 return queryBuilder;
160 -// String dynamicRuleValue = dynamicSearchRuleHelper.getDynamicRuleValue(paramMap); 161 +// queryBuilder = this.buildPersonalSearch(queryBuilder, paramMap);
  162 +// queryBuilder = this.buildFunctionScoreQueryBuild(queryBuilder, paramMap);
  163 +// return queryBuilder;
  164 +
  165 + // String dynamicRuleValue = dynamicSearchRuleHelper.getDynamicRuleValue(paramMap);
161 // if (StringUtils.isEmpty(dynamicRuleValue) || "-1".equals(dynamicRuleValue)) { 166 // if (StringUtils.isEmpty(dynamicRuleValue) || "-1".equals(dynamicRuleValue)) {
162 // queryBuilder = this.buildGlobalSearch(queryBuilder, paramMap); 167 // queryBuilder = this.buildGlobalSearch(queryBuilder, paramMap);
163 // queryBuilder = this.buildDeScoreBrandSearch(queryBuilder, paramMap); 168 // queryBuilder = this.buildDeScoreBrandSearch(queryBuilder, paramMap);
@@ -169,8 +174,9 @@ public class SearchServiceHelper { @@ -169,8 +174,9 @@ public class SearchServiceHelper {
169 174
170 public QueryBuilder constructOrQueryBuilderForProductList(Map<String, String> paramMap) { 175 public QueryBuilder constructOrQueryBuilderForProductList(Map<String, String> paramMap) {
171 QueryBuilder queryBuilder = this.constructOrQueryBuilder(paramMap); 176 QueryBuilder queryBuilder = this.constructOrQueryBuilder(paramMap);
172 - queryBuilder = this.buildPersonalSearch(queryBuilder, paramMap);  
173 - queryBuilder = this.buildFunctionScoreQueryBuild(queryBuilder, paramMap); 177 + queryBuilder = functionScoreSearchHelper.buildFunctionScoreQueryBuild(queryBuilder, paramMap);
  178 +// queryBuilder = this.buildPersonalSearch(queryBuilder, paramMap);
  179 +// queryBuilder = this.buildFunctionScoreQueryBuild(queryBuilder, paramMap);
174 return queryBuilder; 180 return queryBuilder;
175 } 181 }
176 182
@@ -180,15 +186,15 @@ public class SearchServiceHelper { @@ -180,15 +186,15 @@ public class SearchServiceHelper {
180 * @param paramMap 186 * @param paramMap
181 * @return 187 * @return
182 */ 188 */
183 - private QueryBuilder buildPersonalSearch(QueryBuilder queryBuilder, Map<String, String> paramMap) {  
184 - if (!searchCommonHelper.isNeedPersonalSearch(paramMap)) {  
185 - return queryBuilder;  
186 - }  
187 - String uid = paramMap.get("uid");  
188 - String pageId = paramMap.get("pageId");  
189 - QueryBuilder builder = personalizedSearch.builder(queryBuilder, uid, pageId);  
190 - return builder;  
191 - } 189 +// private QueryBuilder buildPersonalSearch(QueryBuilder queryBuilder, Map<String, String> paramMap) {
  190 +// if (!searchCommonHelper.isNeedPersonalSearch(paramMap)) {
  191 +// return queryBuilder;
  192 +// }
  193 +// String uid = paramMap.get("uid");
  194 +// String pageId = paramMap.get("pageId");
  195 +// QueryBuilder builder = personalizedSearch.builder(queryBuilder, uid, pageId);
  196 +// return builder;
  197 +// }
192 198
193 private static float globalWeightFactor = 0.50f; 199 private static float globalWeightFactor = 0.50f;
194 200
@@ -111,6 +111,29 @@ public class SearchSortHelper { @@ -111,6 +111,29 @@ public class SearchSortHelper {
111 } 111 }
112 112
113 /** 113 /**
  114 + * 是否需要优先按分数排序
  115 + *
  116 + * @param paramMap
  117 + * @return
  118 + */
  119 + private boolean isNeedScoreOrderFirst(Map<String, String> paramMap) {
  120 + // 1、模糊搜索且不传order时
  121 + String order = this.getLegalOrder(paramMap);
  122 + if (paramMap.containsKey("query") && StringUtils.isBlank(order)) {
  123 + return true;
  124 + }
  125 + // 2、开了个性化搜索时
  126 + if (searchCommonHelper.isNeedPersonalSearch(paramMap)){
  127 + return true;
  128 + }
  129 + // 3、需要做降分处理时
  130 + if (searchCommonHelper.isNeedDeScoreBrandSearch(paramMap)) {
  131 + return true;
  132 + }
  133 + return false;
  134 + }
  135 +
  136 + /**
114 * 构造排序方式 137 * 构造排序方式
115 * 138 *
116 * @param paramMap 139 * @param paramMap
@@ -119,22 +142,16 @@ public class SearchSortHelper { @@ -119,22 +142,16 @@ public class SearchSortHelper {
119 public List<SortBuilder> buildSortList(Map<String, String> paramMap) { 142 public List<SortBuilder> buildSortList(Map<String, String> paramMap) {
120 List<SortBuilder> sortBuilders = new ArrayList<SortBuilder>(); 143 List<SortBuilder> sortBuilders = new ArrayList<SortBuilder>();
121 List<String> filteredFieldNames = new ArrayList<String>(); 144 List<String> filteredFieldNames = new ArrayList<String>();
122 - // 1、如果需要降分处理,则按_score排序  
123 - if (searchCommonHelper.isNeedDeScoreBrandSearch(paramMap)) { 145 +
  146 + // 1、判断是否需要分数优先
  147 + if (isNeedScoreOrderFirst(paramMap)) {
124 this.addSortBuildSorts(sortBuilders, filteredFieldNames, "_score", SortOrder.DESC); 148 this.addSortBuildSorts(sortBuilders, filteredFieldNames, "_score", SortOrder.DESC);
125 } 149 }
  150 + // 2、处理order
126 String order = this.getLegalOrder(paramMap); 151 String order = this.getLegalOrder(paramMap);
127 - // 2、order为空时  
128 if (StringUtils.isBlank(order)) { 152 if (StringUtils.isBlank(order)) {
129 - // 2.1模糊搜索或个性化搜索,则按_score排序  
130 - if (paramMap.containsKey("query") || searchCommonHelper.isNeedPersonalSearch(paramMap)) {  
131 - this.addSortBuildSorts(sortBuilders, filteredFieldNames, "_score", SortOrder.DESC);  
132 - }  
133 - // 2.2添加次要排序条件  
134 - this.addSortBuildSorts(sortBuilders, filteredFieldNames, "id", SortOrder.DESC);  
135 - return sortBuilders; 153 + order = "";
136 } 154 }
137 - // 3、根据order参数构造  
138 String[] sortTypes = order.split(","); 155 String[] sortTypes = order.split(",");
139 for (String sortType : sortTypes) { 156 for (String sortType : sortTypes) {
140 String[] sortParts = sortType.split(ISearchConstants.SPLIT_CHAR_COLON); 157 String[] sortParts = sortType.split(ISearchConstants.SPLIT_CHAR_COLON);
@@ -153,6 +170,8 @@ public class SearchSortHelper { @@ -153,6 +170,8 @@ public class SearchSortHelper {
153 this.addSortBuildSorts(sortBuilders, filteredFieldNames, fieldName, sortOrder); 170 this.addSortBuildSorts(sortBuilders, filteredFieldNames, fieldName, sortOrder);
154 } 171 }
155 } 172 }
  173 + // 3、任意条件下,都要添加次要排序条件
  174 + this.addSortBuildSorts(sortBuilders, filteredFieldNames, "shelveTime", SortOrder.DESC);
156 this.addSortBuildSorts(sortBuilders, filteredFieldNames, "id", SortOrder.DESC); 175 this.addSortBuildSorts(sortBuilders, filteredFieldNames, "id", SortOrder.DESC);
157 return sortBuilders; 176 return sortBuilders;
158 } 177 }