Authored by Gino Zhang

Merge branch 'master' into zf_smart_search2

@@ -45,10 +45,10 @@ public class FunctionScoreSearchHelper { @@ -45,10 +45,10 @@ public class FunctionScoreSearchHelper {
45 45
46 public QueryBuilder buildFunctionScoreQueryBuild(QueryBuilder queryBuilder, Map<String, String> paramMap) { 46 public QueryBuilder buildFunctionScoreQueryBuild(QueryBuilder queryBuilder, Map<String, String> paramMap) {
47 FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder); 47 FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder);
48 - // 将某个SKN展示到第一个 48 + // 将某些SKN展示到前面
49 if (searchCommonHelper.isFirstProductSknSearch(paramMap)) { 49 if (searchCommonHelper.isFirstProductSknSearch(paramMap)) {
50 - functionScoreQueryBuilder.add(QueryBuilders.termQuery("productSkn", paramMap.get(SearchRequestParams.FIRST_PRODUCRSKN)),  
51 - ScoreFunctionBuilders.weightFactorFunction(1000)); 50 + String[] productSkns = paramMap.get(SearchRequestParams.FIRST_PRODUCRSKN).split(",");
  51 + functionScoreQueryBuilder.add(QueryBuilders.termsQuery("productSkn",productSkns),ScoreFunctionBuilders.weightFactorFunction(1000));
52 } 52 }
53 if (searchCommonHelper.isNeedPersonalSearch(paramMap)) { 53 if (searchCommonHelper.isNeedPersonalSearch(paramMap)) {
54 personalVectorFeatureSearch.addPersonalizedScriptScore(functionScoreQueryBuilder, paramMap); 54 personalVectorFeatureSearch.addPersonalizedScriptScore(functionScoreQueryBuilder, paramMap);
1 package com.yoho.search.service.service.helper; 1 package com.yoho.search.service.service.helper;
2 2
  3 +import java.io.UnsupportedEncodingException;
  4 +import java.net.URLDecoder;
  5 +import java.util.ArrayList;
  6 +import java.util.Arrays;
  7 +import java.util.Date;
  8 +import java.util.HashMap;
  9 +import java.util.Iterator;
  10 +import java.util.List;
  11 +import java.util.Map;
  12 +
  13 +import org.apache.commons.collections.CollectionUtils;
  14 +import org.apache.commons.lang.StringUtils;
  15 +import org.elasticsearch.index.query.BoolQueryBuilder;
  16 +import org.elasticsearch.index.query.MatchQueryBuilder;
  17 +import org.elasticsearch.index.query.MultiMatchQueryBuilder;
  18 +import org.elasticsearch.index.query.QueryBuilder;
  19 +import org.elasticsearch.index.query.QueryBuilders;
  20 +import org.slf4j.Logger;
  21 +import org.slf4j.LoggerFactory;
  22 +import org.springframework.beans.factory.annotation.Autowired;
  23 +import org.springframework.stereotype.Service;
  24 +
3 import com.yoho.search.base.utils.ConvertUtils; 25 import com.yoho.search.base.utils.ConvertUtils;
4 import com.yoho.search.base.utils.DateUtil; 26 import com.yoho.search.base.utils.DateUtil;
5 import com.yoho.search.base.utils.ISearchConstants; 27 import com.yoho.search.base.utils.ISearchConstants;
@@ -12,18 +34,6 @@ import com.yoho.search.service.service.SearchDynamicConfigService; @@ -12,18 +34,6 @@ import com.yoho.search.service.service.SearchDynamicConfigService;
12 import com.yoho.search.service.service.SearchKeyWordService; 34 import com.yoho.search.service.service.SearchKeyWordService;
13 import com.yoho.search.service.utils.SearchRequestParams; 35 import com.yoho.search.service.utils.SearchRequestParams;
14 36
15 -import org.apache.commons.collections.CollectionUtils;  
16 -import org.apache.commons.lang.StringUtils;  
17 -import org.elasticsearch.index.query.*;  
18 -import org.slf4j.Logger;  
19 -import org.slf4j.LoggerFactory;  
20 -import org.springframework.beans.factory.annotation.Autowired;  
21 -import org.springframework.stereotype.Service;  
22 -  
23 -import java.io.UnsupportedEncodingException;  
24 -import java.net.URLDecoder;  
25 -import java.util.*;  
26 -  
27 @Service 37 @Service
28 public class SearchServiceHelper { 38 public class SearchServiceHelper {
29 39
@@ -82,59 +92,59 @@ public class SearchServiceHelper { @@ -82,59 +92,59 @@ public class SearchServiceHelper {
82 return queryBuilder; 92 return queryBuilder;
83 } 93 }
84 94
85 - /**  
86 - * 构造关键字查询的query  
87 - *  
88 - * @param paramMap  
89 - * @return  
90 - */  
91 - public QueryBuilder constructQueryBuilder(Map<String, String> paramMap) {  
92 - String keyword = paramMap.get("query");  
93 - if (StringUtils.isBlank(keyword)) {  
94 - return QueryBuilders.matchAllQuery();  
95 - }  
96 - // 0、处理is_encode的情况,编码转换  
97 - String is_encode = paramMap.get("is_encode");  
98 - if (StringUtils.isNotBlank(is_encode) && is_encode.equals("1")) {  
99 - try {  
100 - keyword = URLDecoder.decode(keyword, "UTF-8");  
101 - } catch (UnsupportedEncodingException e) {  
102 - logger.warn(e.getMessage(), e);  
103 - }  
104 - }  
105 - paramMap.put("query", keyword);  
106 -  
107 - // 1、处理查询中包含性别的情况  
108 - searchCommonHelper.dealKeywordOfGender(keyword, paramMap);  
109 -  
110 - // 2、构建多字段匹配【keyword需要有一个默认的查询字段以及权重设置,就可以拼接成一个sql】  
111 - MultiMatchQueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(keyword);  
112 - MultiMatchQueryBuilder.Type multiMatchQueryBuilderType = searchCommonHelper.getMultiMatchQueryBuilderType();  
113 - if (multiMatchQueryBuilderType != null) {  
114 - queryBuilder.type(multiMatchQueryBuilderType);  
115 - }  
116 -  
117 - // 3.如果查询的是skn,则直接走productSkn_ansj这个字段  
118 - if (searchCommonHelper.isQuerySkn(keyword)) {  
119 - queryBuilder.field("productSkn.productSkn_ansj");  
120 - queryBuilder.operator(MatchQueryBuilder.Operator.OR);  
121 - return queryBuilder;  
122 - }  
123 -  
124 - // 4.设置查询字段和比重【AND表示多字段都要匹配,可提高精确度】  
125 - this.setDefaultSearchField(queryBuilder, paramMap);  
126 - if (ISearchConstants.SEARCH_OPERATOR.equalsIgnoreCase("or")) {  
127 - queryBuilder.operator(MatchQueryBuilder.Operator.OR);  
128 - queryBuilder.minimumShouldMatch(ISearchConstants.SEARCH_MINIMUM_SHOULD_MATCH);  
129 - } else {  
130 - queryBuilder.operator(MatchQueryBuilder.Operator.AND);  
131 - }  
132 -  
133 - // 5.如果不是skn,则将搜索关键词存进redis  
134 - searchKeyWordService.recordKeyWord(keyword);  
135 -  
136 - return queryBuilder;  
137 - } 95 + /**
  96 + * 构造关键字查询的query
  97 + *
  98 + * @param paramMap
  99 + * @return
  100 + */
  101 + public QueryBuilder constructQueryBuilder(Map<String, String> paramMap) {
  102 + String keyword = paramMap.get("query");
  103 + if (StringUtils.isBlank(keyword)) {
  104 + return QueryBuilders.matchAllQuery();
  105 + }
  106 + // 0、处理is_encode的情况,编码转换
  107 + String is_encode = paramMap.get("is_encode");
  108 + if (StringUtils.isNotBlank(is_encode) && is_encode.equals("1")) {
  109 + try {
  110 + keyword = URLDecoder.decode(keyword, "UTF-8");
  111 + } catch (UnsupportedEncodingException e) {
  112 + logger.warn(e.getMessage(), e);
  113 + }
  114 + }
  115 + paramMap.put("query", keyword);
  116 +
  117 + // 1、处理查询中包含性别的情况
  118 + searchCommonHelper.dealKeywordOfGender(keyword, paramMap);
  119 +
  120 + // 2、构建多字段匹配【keyword需要有一个默认的查询字段以及权重设置,就可以拼接成一个sql】
  121 + MultiMatchQueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(keyword);
  122 + MultiMatchQueryBuilder.Type multiMatchQueryBuilderType = searchCommonHelper.getMultiMatchQueryBuilderType();
  123 + if (multiMatchQueryBuilderType != null) {
  124 + queryBuilder.type(multiMatchQueryBuilderType);
  125 + }
  126 +
  127 + // 3.如果查询的是skn,则直接走productSkn_ansj这个字段
  128 + if (searchCommonHelper.isQuerySkn(keyword)) {
  129 + queryBuilder.field("productSkn.productSkn_ansj");
  130 + queryBuilder.operator(MatchQueryBuilder.Operator.OR);
  131 + return queryBuilder;
  132 + }
  133 +
  134 + // 4.设置查询字段和比重【AND表示多字段都要匹配,可提高精确度】
  135 + this.setDefaultSearchField(queryBuilder, paramMap);
  136 + if (ISearchConstants.SEARCH_OPERATOR.equalsIgnoreCase("or")) {
  137 + queryBuilder.operator(MatchQueryBuilder.Operator.OR);
  138 + queryBuilder.minimumShouldMatch(ISearchConstants.SEARCH_MINIMUM_SHOULD_MATCH);
  139 + } else {
  140 + queryBuilder.operator(MatchQueryBuilder.Operator.AND);
  141 + }
  142 +
  143 + // 5.如果不是skn,则将搜索关键词存进redis
  144 + searchKeyWordService.recordKeyWord(keyword);
  145 +
  146 + return queryBuilder;
  147 + }
138 148
139 /** 149 /**
140 * 构建商品列表的QueryBuilder 150 * 构建商品列表的QueryBuilder
@@ -255,6 +265,15 @@ public class SearchServiceHelper { @@ -255,6 +265,15 @@ public class SearchServiceHelper {
255 int[] smallsortids = ConvertUtils.stringToIntArray(paramMap.get(SearchRequestParams.PARAM_SEARCH_SMALLSORT), ","); 265 int[] smallsortids = ConvertUtils.stringToIntArray(paramMap.get(SearchRequestParams.PARAM_SEARCH_SMALLSORT), ",");
256 boolFilter.must(QueryBuilders.termsQuery("smallSortId", smallsortids)); 266 boolFilter.must(QueryBuilders.termsQuery("smallSortId", smallsortids));
257 } 267 }
  268 + // 大中小分类
  269 + if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_COMMONSORT) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_COMMONSORT))) {
  270 + int[] commonSortIds = ConvertUtils.stringToIntArray(paramMap.get(SearchRequestParams.PARAM_SEARCH_COMMONSORT), ",");
  271 + BoolQueryBuilder commonSortIdFilter = QueryBuilders.boolQuery();
  272 + commonSortIdFilter.should(QueryBuilders.termsQuery("maxSortId", commonSortIds));
  273 + commonSortIdFilter.should(QueryBuilders.termsQuery("middleSortId", commonSortIds));
  274 + commonSortIdFilter.should(QueryBuilders.termsQuery("smallSortId", commonSortIds));
  275 + boolFilter.must(commonSortIdFilter);
  276 + }
258 // 颜色 277 // 颜色
259 if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_COLOR) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_COLOR)) 278 if (paramMap.containsKey(SearchRequestParams.PARAM_SEARCH_COLOR) && StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_COLOR))
260 && !SearchRequestParams.PARAM_SEARCH_COLOR.equals(filterParamName)) { 279 && !SearchRequestParams.PARAM_SEARCH_COLOR.equals(filterParamName)) {
@@ -492,6 +511,14 @@ public class SearchServiceHelper { @@ -492,6 +511,14 @@ public class SearchServiceHelper {
492 if (!paramMap.containsKey("contain_seckill") || !"Y".equals(paramMap.get("contain_seckill"))) { 511 if (!paramMap.containsKey("contain_seckill") || !"Y".equals(paramMap.get("contain_seckill"))) {
493 boolFilter.mustNot(QueryBuilders.termsQuery("isSeckill", "Y")); 512 boolFilter.mustNot(QueryBuilders.termsQuery("isSeckill", "Y"));
494 } 513 }
  514 + // 用户VIP级别过滤
  515 + String userVipLevel = (paramMap.get(SearchRequestParams.USER_VIP_LEVEL));
  516 + if (StringUtils.isNotBlank(userVipLevel)) {
  517 + List<String> userVipLevels = this.getUserVipLevels(userVipLevel);
  518 + if (userVipLevels != null) {
  519 + boolFilter.must(QueryBuilders.termsQuery("vipLevels", userVipLevels));
  520 + }
  521 + }
495 // 通用的过滤请求 522 // 通用的过滤请求
496 for (String key : paramMap.keySet()) { 523 for (String key : paramMap.keySet()) {
497 if (key.startsWith("not_")) { 524 if (key.startsWith("not_")) {
@@ -514,6 +541,19 @@ public class SearchServiceHelper { @@ -514,6 +541,19 @@ public class SearchServiceHelper {
514 } 541 }
515 } 542 }
516 543
  544 + private List<String> getUserVipLevels(String userVipLevel) {
  545 + if ("1".equals(userVipLevel)) {
  546 + return Arrays.asList("1");
  547 + }
  548 + if ("2".equals(userVipLevel)) {
  549 + return Arrays.asList("1", "2");
  550 + }
  551 + if ("3".equals(userVipLevel)) {
  552 + return Arrays.asList("1", "2", "3");
  553 + }
  554 + return null;
  555 + }
  556 +
517 public Map<String, List<Map<String, Object>>> getProductPricePlanMap(SearchResult searchProductPricePlanResult) { 557 public Map<String, List<Map<String, Object>>> getProductPricePlanMap(SearchResult searchProductPricePlanResult) {
518 Map<String, List<Map<String, Object>>> productPricePlanMap = new HashMap<String, List<Map<String, Object>>>(); 558 Map<String, List<Map<String, Object>>> productPricePlanMap = new HashMap<String, List<Map<String, Object>>>();
519 if (searchProductPricePlanResult == null || searchProductPricePlanResult.getResultList() == null || searchProductPricePlanResult.getResultList().size() == 0) { 559 if (searchProductPricePlanResult == null || searchProductPricePlanResult.getResultList() == null || searchProductPricePlanResult.getResultList().size() == 0) {
@@ -720,7 +760,7 @@ public class SearchServiceHelper { @@ -720,7 +760,7 @@ public class SearchServiceHelper {
720 productMap.put("tbl_country_name", map.get("tblCountryName")); 760 productMap.put("tbl_country_name", map.get("tblCountryName"));
721 String tbl_plane = (tbl_country_id != null && tbl_country_id != 86) ? "Y" : "N"; 761 String tbl_plane = (tbl_country_id != null && tbl_country_id != 86) ? "Y" : "N";
722 productMap.put("tbl_plane", tbl_plane); 762 productMap.put("tbl_plane", tbl_plane);
723 - productMap.put("skn_default_img", map.get("sknDefaultImg")); 763 + productMap.put("skn_default_img", map.get("sknDefaultImg"));
724 return productMap; 764 return productMap;
725 } 765 }
726 } 766 }
@@ -6,6 +6,8 @@ public class SearchRequestParams { @@ -6,6 +6,8 @@ public class SearchRequestParams {
6 public static final String PARAM_SEARCH_MAXSORT = "msort"; // 查询大类 6 public static final String PARAM_SEARCH_MAXSORT = "msort"; // 查询大类
7 public static final String PARAM_SEARCH_MIDDLESORT = "misort"; // 查询中类 7 public static final String PARAM_SEARCH_MIDDLESORT = "misort"; // 查询中类
8 public static final String PARAM_SEARCH_SMALLSORT = "sort"; // 查询小类 8 public static final String PARAM_SEARCH_SMALLSORT = "sort"; // 查询小类
  9 + public static final String PARAM_SEARCH_COMMONSORT = "common_sort";//不区分大中小分类的品类id
  10 +
9 public static final String PARAM_SEARCH_GENDER = "gender"; // 查询男女款 11 public static final String PARAM_SEARCH_GENDER = "gender"; // 查询男女款
10 public static final String PARAM_SEARCH_AGELEVEL = "ageLevel"; // 查询年龄段 12 public static final String PARAM_SEARCH_AGELEVEL = "ageLevel"; // 查询年龄段
11 public static final String PARAM_SEARCH_APPTYPE = "app_type"; // APP类型 13 public static final String PARAM_SEARCH_APPTYPE = "app_type"; // APP类型
@@ -87,4 +89,6 @@ public class SearchRequestParams { @@ -87,4 +89,6 @@ public class SearchRequestParams {
87 public static final String FIRST_PRODUCRSKN = "firstProductSkn"; 89 public static final String FIRST_PRODUCRSKN = "firstProductSkn";
88 public static final String PHYSICAL_CHANNEL = "physical_channel"; 90 public static final String PHYSICAL_CHANNEL = "physical_channel";
89 91
  92 + public static final String USER_VIP_LEVEL = "userVipLevel";
  93 +
90 } 94 }