走conversion的情况不再出现组合词,直接走精确匹配,效果更好
Showing
1 changed file
with
67 additions
and
37 deletions
@@ -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")); |
-
Please register or login to post a comment