Authored by Gino Zhang

走conversion的情况不再出现组合词,直接走精确匹配,效果更好

@@ -113,7 +113,7 @@ public class SearchRecommendServiceImpl implements ISearchRecommendService { @@ -113,7 +113,7 @@ public class SearchRecommendServiceImpl implements ISearchRecommendService {
113 Double count = searchKeyWordService.getKeywordCount(RedisKeys.YOHO_SEARCH_KEYWORDS_EMPTY, queryWord); 113 Double count = searchKeyWordService.getKeywordCount(RedisKeys.YOHO_SEARCH_KEYWORDS_EMPTY, queryWord);
114 if (count == null || queryWord.length() >= 5) { 114 if (count == null || queryWord.length() >= 5) {
115 // 1.3) 如果该关键词一次都没有出现在空结果列表或者长度大于5 则该词很有可能是可以搜索出结果的 因此优先取suggest去搜索一把 减少后面的查询动作 115 // 1.3) 如果该关键词一次都没有出现在空结果列表或者长度大于5 则该词很有可能是可以搜索出结果的 因此优先取suggest去搜索一把 减少后面的查询动作
116 - JSONObject recommendResult = recommendBySuggestIndex(paramMap, keywordsToSearch); 116 + JSONObject recommendResult = recommendBySuggestIndex(paramMap, keywordsToSearch, false);
117 if (recommendResult == null) { 117 if (recommendResult == null) {
118 return defaultSuggestRecommendation(); 118 return defaultSuggestRecommendation();
119 } else if (CollectionUtils.isNotEmpty((List) recommendResult.get("terms_suggestion"))) { 119 } else if (CollectionUtils.isNotEmpty((List) recommendResult.get("terms_suggestion"))) {
@@ -135,7 +135,7 @@ public class SearchRecommendServiceImpl implements ISearchRecommendService { @@ -135,7 +135,7 @@ public class SearchRecommendServiceImpl implements ISearchRecommendService {
135 return defaultSuggestRecommendation(); 135 return defaultSuggestRecommendation();
136 } 136 }
137 137
138 - JSONObject recommendResult = recommendBySuggestIndex(paramMap, keywordsToSearch); 138 + JSONObject recommendResult = recommendBySuggestIndex(paramMap, keywordsToSearch, dest != null);
139 if (recommendResult == null || CollectionUtils.isEmpty((List) recommendResult.get("terms_suggestion"))) { 139 if (recommendResult == null || CollectionUtils.isEmpty((List) recommendResult.get("terms_suggestion"))) {
140 recommendResult = defaultSuggestRecommendation(); 140 recommendResult = defaultSuggestRecommendation();
141 } 141 }
@@ -182,9 +182,10 @@ public class SearchRecommendServiceImpl implements ISearchRecommendService { @@ -182,9 +182,10 @@ public class SearchRecommendServiceImpl implements ISearchRecommendService {
182 * 182 *
183 * @param paramMap 搜索参数,用于判断取哪个count 183 * @param paramMap 搜索参数,用于判断取哪个count
184 * @param keywordsToSearch 计算获取的推荐词列表 184 * @param keywordsToSearch 计算获取的推荐词列表
  185 + * @param isLimitKeywords 是否限制只能是推荐词列表里面的词
185 * @return 搜推荐结果 186 * @return 搜推荐结果
186 */ 187 */
187 - private JSONObject recommendBySuggestIndex(Map<String, String> paramMap, String keywordsToSearch) { 188 + private JSONObject recommendBySuggestIndex(Map<String, String> paramMap, String keywordsToSearch, boolean isLimitKeywords) {
188 String srcQueryWord = paramMap.get(SearchRequestParams.PARAM_SEARCH_KEYWORD); 189 String srcQueryWord = paramMap.get(SearchRequestParams.PARAM_SEARCH_KEYWORD);
189 long begin = System.currentTimeMillis(); 190 long begin = System.currentTimeMillis();
190 logger.info("[func=recommendBySuggestIndex][srcQueryWord={}][keywordsToSearch={}][begin={}]", srcQueryWord, keywordsToSearch, begin); 191 logger.info("[func=recommendBySuggestIndex][srcQueryWord={}][keywordsToSearch={}][begin={}]", srcQueryWord, keywordsToSearch, begin);
@@ -195,7 +196,13 @@ public class SearchRecommendServiceImpl implements ISearchRecommendService { @@ -195,7 +196,13 @@ public class SearchRecommendServiceImpl implements ISearchRecommendService {
195 } 196 }
196 197
197 // 2) 先对keywordsToSearch进行分词 198 // 2) 先对keywordsToSearch进行分词
198 - List<String> terms = searchKeyWordService.getAnalyzeTerms(keywordsToSearch, "ik_smart", true); 199 + List<String> terms = null;
  200 + if (isLimitKeywords) {
  201 + terms = Arrays.stream(keywordsToSearch.split(",")).filter(term -> term != null && term.length() > 1).distinct().collect(Collectors.toList());
  202 + } else {
  203 + terms = searchKeyWordService.getAnalyzeTerms(keywordsToSearch, "ik_smart", true);
  204 + }
  205 +
199 if (CollectionUtils.isEmpty(terms)) { 206 if (CollectionUtils.isEmpty(terms)) {
200 return new JSONObject(); 207 return new JSONObject();
201 } 208 }
@@ -207,39 +214,8 @@ public class SearchRecommendServiceImpl implements ISearchRecommendService { @@ -207,39 +214,8 @@ public class SearchRecommendServiceImpl implements ISearchRecommendService {
207 final String countField = suggestService.getCountField(paramMap); 214 final String countField = suggestService.getCountField(paramMap);
208 SearchParam searchParam = new SearchParam(); 215 SearchParam searchParam = new SearchParam();
209 216
210 - // 3.1) 对于suggest的multi-fields至少要有一个字段匹配到 匹配打分为常量1  
211 - MultiMatchQueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(keywordsToSearch.trim().toLowerCase(),  
212 - "keyword", "keyword.keyword_ik", "keyword.keyword_pinyin", "keyword.keyword_jianpin", "keyword.keyword_lowercase")  
213 - .analyzer("ik_smart")  
214 - .type(MultiMatchQueryBuilder.Type.BEST_FIELDS)  
215 - .operator(MatchQueryBuilder.Operator.OR)  
216 - .minimumShouldMatch("1");  
217 -  
218 -  
219 - FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(QueryBuilders.constantScoreQuery(queryBuilder));  
220 - for (String term : termSet) {  
221 - // 3.2) 对于完全匹配Term的加1分  
222 - functionScoreQueryBuilder.add(QueryBuilders.termQuery("standardKeyword", CharUtils.standardized(term)),  
223 - ScoreFunctionBuilders.weightFactorFunction(1));  
224 -  
225 - // 3.3) 对于匹配到一个Term的加2分  
226 - functionScoreQueryBuilder.add(QueryBuilders.termQuery("keyword.keyword_ik", term),  
227 - ScoreFunctionBuilders.weightFactorFunction(2));  
228 - }  
229 -  
230 - // 3.4) 处理性别相关的关键词  
231 - if (terms.contains("男") && !terms.contains("女")) {  
232 - // 给女生相关减分  
233 - functionScoreQueryBuilder.add(QueryBuilders.termQuery("keyword.keyword_ik", "女"),  
234 - ScoreFunctionBuilders.weightFactorFunction(-5));  
235 - } else if (!terms.contains("男") && terms.contains("女")) {  
236 - // 给男生相关减分  
237 - functionScoreQueryBuilder.add(QueryBuilders.termQuery("keyword.keyword_ik", "男"),  
238 - ScoreFunctionBuilders.weightFactorFunction(-5));  
239 - }  
240 -  
241 - functionScoreQueryBuilder.boostMode(CombineFunction.SUM);  
242 - searchParam.setQuery(functionScoreQueryBuilder); 217 + QueryBuilder queryBuilder = isLimitKeywords ? buildQueryBuilderByLimit(terms) : buildQueryBuilder(keywordsToSearch, termSet);
  218 + searchParam.setQuery(queryBuilder);
243 searchParam.setPage(1); 219 searchParam.setPage(1);
244 searchParam.setSize(SMART_SUGGESTION_TERM_COUNT); 220 searchParam.setSize(SMART_SUGGESTION_TERM_COUNT);
245 221
@@ -248,6 +224,9 @@ public class SearchRecommendServiceImpl implements ISearchRecommendService { @@ -248,6 +224,9 @@ public class SearchRecommendServiceImpl implements ISearchRecommendService {
248 boolFilter.must(QueryBuilders.termQuery("status", VALID_STATUS)); 224 boolFilter.must(QueryBuilders.termQuery("status", VALID_STATUS));
249 boolFilter.must(QueryBuilders.rangeQuery(countField).gte(SMART_SUGGESTION_COUNT_LIMIT)); 225 boolFilter.must(QueryBuilders.rangeQuery(countField).gte(SMART_SUGGESTION_COUNT_LIMIT));
250 boolFilter.mustNot(QueryBuilders.termQuery("standardKeyword", CharUtils.standardized(srcQueryWord))); 226 boolFilter.mustNot(QueryBuilders.termQuery("standardKeyword", CharUtils.standardized(srcQueryWord)));
  227 + if (isLimitKeywords) {
  228 + boolFilter.must(QueryBuilders.termsQuery("standardKeyword", termSet.stream().map(term -> CharUtils.standardized(term)).collect(Collectors.toList())));
  229 + }
251 searchParam.setFiter(boolFilter); 230 searchParam.setFiter(boolFilter);
252 231
253 // 3.6) 按照得分、权重、数量的规则降序排序 232 // 3.6) 按照得分、权重、数量的规则降序排序
@@ -281,6 +260,57 @@ public class SearchRecommendServiceImpl implements ISearchRecommendService { @@ -281,6 +260,57 @@ public class SearchRecommendServiceImpl implements ISearchRecommendService {
281 return suggestResult; 260 return suggestResult;
282 } 261 }
283 262
  263 + private QueryBuilder buildQueryBuilderByLimit(List<String> terms) {
  264 + FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(QueryBuilders.matchAllQuery());
  265 +
  266 + // 给品类类型的关键词加分
  267 + functionScoreQueryBuilder.add(QueryBuilders.termQuery("type", Integer.valueOf(2)),
  268 + ScoreFunctionBuilders.weightFactorFunction(3));
  269 +
  270 + // 按词出现的顺序加分
  271 + for (int i = 0; i < terms.size(); i++) {
  272 + functionScoreQueryBuilder.add(QueryBuilders.termQuery("standardKeyword", CharUtils.standardized(terms.get(i))),
  273 + ScoreFunctionBuilders.weightFactorFunction(terms.size() - i));
  274 + }
  275 +
  276 + functionScoreQueryBuilder.boostMode(CombineFunction.SUM);
  277 + return functionScoreQueryBuilder;
  278 + }
  279 +
  280 + private QueryBuilder buildQueryBuilder(String keywordsToSearch, Set<String> termSet) {
  281 + // 3.1) 对于suggest的multi-fields至少要有一个字段匹配到 匹配打分为常量1
  282 + MultiMatchQueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(keywordsToSearch.trim().toLowerCase(),
  283 + "keyword", "keyword.keyword_ik", "keyword.keyword_pinyin", "keyword.keyword_jianpin", "keyword.keyword_lowercase")
  284 + .analyzer("ik_smart")
  285 + .type(MultiMatchQueryBuilder.Type.BEST_FIELDS)
  286 + .operator(MatchQueryBuilder.Operator.OR)
  287 + .minimumShouldMatch("1");
  288 +
  289 +
  290 + FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(QueryBuilders.constantScoreQuery(queryBuilder));
  291 + for (String term : termSet) {
  292 + // 3.2) 对于完全匹配Term的加1分
  293 + functionScoreQueryBuilder.add(QueryBuilders.termQuery("standardKeyword", CharUtils.standardized(term)),
  294 + ScoreFunctionBuilders.weightFactorFunction(1));
  295 +
  296 + // 3.3) 对于匹配到一个Term的加2分
  297 + functionScoreQueryBuilder.add(QueryBuilders.termQuery("keyword.keyword_ik", term),
  298 + ScoreFunctionBuilders.weightFactorFunction(2));
  299 + }
  300 +
  301 + // 3.4) 处理性别相关的关键词
  302 + if (termSet.contains("男") && !termSet.contains("女")) {
  303 + functionScoreQueryBuilder.add(QueryBuilders.termQuery("keyword.keyword_ik", "女"),
  304 + ScoreFunctionBuilders.weightFactorFunction(-5));
  305 + } else if (!termSet.contains("男") && termSet.contains("女")) {
  306 + functionScoreQueryBuilder.add(QueryBuilders.termQuery("keyword.keyword_ik", "男"),
  307 + ScoreFunctionBuilders.weightFactorFunction(-5));
  308 + }
  309 +
  310 + functionScoreQueryBuilder.boostMode(CombineFunction.SUM);
  311 + return functionScoreQueryBuilder;
  312 + }
  313 +
284 private boolean containsProductInSearchResult(SearchApiResult searchResult) { 314 private boolean containsProductInSearchResult(SearchApiResult searchResult) {
285 JSONObject dataMap = ((JSONObject) searchResult.getData()); 315 JSONObject dataMap = ((JSONObject) searchResult.getData());
286 return CollectionUtils.isNotEmpty((List) dataMap.get("product_list")); 316 return CollectionUtils.isNotEmpty((List) dataMap.get("product_list"));