Authored by hugufei

代码优化

@@ -4,7 +4,7 @@ import java.util.Map; @@ -4,7 +4,7 @@ import java.util.Map;
4 4
5 import javax.servlet.http.HttpServletRequest; 5 import javax.servlet.http.HttpServletRequest;
6 6
7 -import com.yoho.search.service.scene.searchlike.BigdataSimilarSknService; 7 +import com.yoho.search.service.scene.searchlike.SearchLikeNotInShopService;
8 import com.yoho.search.service.scene.searchlike.SearchLikeHelper; 8 import com.yoho.search.service.scene.searchlike.SearchLikeHelper;
9 import org.apache.commons.collections.MapUtils; 9 import org.apache.commons.collections.MapUtils;
10 import org.springframework.beans.factory.annotation.Autowired; 10 import org.springframework.beans.factory.annotation.Autowired;
@@ -38,7 +38,7 @@ public class SearchLikeSecneController { @@ -38,7 +38,7 @@ public class SearchLikeSecneController {
38 @Autowired 38 @Autowired
39 private SimilarProductService similarProductService; 39 private SimilarProductService similarProductService;
40 @Autowired 40 @Autowired
41 - private BigdataSimilarSknService bigdataSimilarSknService; 41 + private SearchLikeNotInShopService searchLikeNotInShopService;
42 @Autowired 42 @Autowired
43 private SearchLikeHelper searchLikeHelper; 43 private SearchLikeHelper searchLikeHelper;
44 44
@@ -63,7 +63,7 @@ public class SearchLikeSecneController { @@ -63,7 +63,7 @@ public class SearchLikeSecneController {
63 public SearchApiResult searchLikeNotInShop(HttpServletRequest request) { 63 public SearchApiResult searchLikeNotInShop(HttpServletRequest request) {
64 Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request); 64 Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
65 int viewNum = MapUtils.getIntValue(paramMap,"viewNum",10); 65 int viewNum = MapUtils.getIntValue(paramMap,"viewNum",10);
66 - SearchApiResult result = bigdataSimilarSknService.searchLikeSimilarSknNotInShop(paramMap); 66 + SearchApiResult result = searchLikeNotInShopService.searchLikeSimilarSknNotInShop(paramMap);
67 return searchLikeHelper.buildSearchApiResultWithViewNum(result,viewNum); 67 return searchLikeHelper.buildSearchApiResultWithViewNum(result,viewNum);
68 } 68 }
69 69
@@ -2,6 +2,7 @@ package com.yoho.search.service.index; @@ -2,6 +2,7 @@ package com.yoho.search.service.index;
2 2
3 import com.yoho.search.base.utils.ISearchConstants; 3 import com.yoho.search.base.utils.ISearchConstants;
4 import com.yoho.search.base.utils.ProductIndexEsField; 4 import com.yoho.search.base.utils.ProductIndexEsField;
  5 +import com.yoho.search.bo.BigdataSimilarSknIndexBO;
5 import com.yoho.search.core.es.model.SearchParam; 6 import com.yoho.search.core.es.model.SearchParam;
6 import com.yoho.search.core.es.model.SearchResult; 7 import com.yoho.search.core.es.model.SearchResult;
7 import com.yoho.search.dal.model.BigdataSimilarSkn; 8 import com.yoho.search.dal.model.BigdataSimilarSkn;
@@ -26,7 +27,7 @@ public class BigdataSimilarSknIndexBaseService { @@ -26,7 +27,7 @@ public class BigdataSimilarSknIndexBaseService {
26 @Autowired 27 @Autowired
27 private SearchCommonService searchCommonService; 28 private SearchCommonService searchCommonService;
28 29
29 - public BigdataSimilarSkn querySimilarSkn(String productSkn) { 30 + public BigdataSimilarSknIndexBO querySimilarSkn(String productSkn) {
30 try { 31 try {
31 SearchParam searchParam = new SearchParam(); 32 SearchParam searchParam = new SearchParam();
32 BoolQueryBuilder boolFilter = QueryBuilders.boolQuery(); 33 BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
@@ -45,7 +46,7 @@ public class BigdataSimilarSknIndexBaseService { @@ -45,7 +46,7 @@ public class BigdataSimilarSknIndexBaseService {
45 return null; 46 return null;
46 } 47 }
47 Map<String, Object> result = similarSknResults.get(0); 48 Map<String, Object> result = similarSknResults.get(0);
48 - BigdataSimilarSkn bigdataSimilarSkn = new BigdataSimilarSkn(); 49 + BigdataSimilarSknIndexBO bigdataSimilarSkn = new BigdataSimilarSknIndexBO();
49 BeanUtils.populate(bigdataSimilarSkn, result); 50 BeanUtils.populate(bigdataSimilarSkn, result);
50 return bigdataSimilarSkn; 51 return bigdataSimilarSkn;
51 }catch (Exception e){ 52 }catch (Exception e){
@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONArray; @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONArray;
4 import com.alibaba.fastjson.JSONObject; 4 import com.alibaba.fastjson.JSONObject;
5 import com.yoho.search.base.utils.ISearchConstants; 5 import com.yoho.search.base.utils.ISearchConstants;
6 import com.yoho.search.base.utils.ProductIndexEsField; 6 import com.yoho.search.base.utils.ProductIndexEsField;
  7 +import com.yoho.search.base.utils.SearchCollectionUtils;
7 import com.yoho.search.common.SearchCommonService; 8 import com.yoho.search.common.SearchCommonService;
8 import com.yoho.search.core.es.model.SearchParam; 9 import com.yoho.search.core.es.model.SearchParam;
9 import com.yoho.search.core.es.model.SearchResult; 10 import com.yoho.search.core.es.model.SearchResult;
@@ -428,4 +429,51 @@ public class SearchLikeHelper { @@ -428,4 +429,51 @@ public class SearchLikeHelper {
428 return boolFilter; 429 return boolFilter;
429 } 430 }
430 431
  432 + /**
  433 + * 获取非重复skn
  434 + *
  435 + * @param productSknStr
  436 + * @return
  437 + */
  438 + public List<String> getDistinctSknList(String productSknStr) {
  439 + List<String> results = new ArrayList<>();
  440 + String[] productSkns = productSknStr.split(",");
  441 + for (String productSkn : productSkns) {
  442 + if (!results.contains(productSkn) && StringUtils.isNumeric(productSkn)) {
  443 + results.add(productSkn);
  444 + }
  445 + }
  446 + return results;
  447 + }
  448 +
  449 + /**
  450 + * 按productSkn顺序截取商品条数-注意循环引用的问题
  451 + *
  452 + * @param esProductList
  453 + * @param sortedProductSkns
  454 + * @param size
  455 + * @return
  456 + */
  457 + public List<Map<String, Object>> sortProductList(List<Map<String, Object>> esProductList, List<String> sortedProductSkns, int size) {
  458 + List<Map<String, Object>> results = new ArrayList<>();
  459 + if (esProductList == null || esProductList.isEmpty()) {
  460 + return results;
  461 + }
  462 + if (sortedProductSkns == null || sortedProductSkns.isEmpty() || size <= 0) {
  463 + return results;
  464 + }
  465 + Map<String, Map<String, Object>> productMap = SearchCollectionUtils.toMap(esProductList, (product) -> MapUtils.getString(product, ProductIndexEsField.productSkn, ""));
  466 + for (String productSkn : sortedProductSkns) {
  467 + if (productMap.containsKey(productSkn)) {
  468 + results.add(new HashMap<>(productMap.get(productSkn)));//注意循环引用
  469 + }
  470 + if (results.size() >= size) {
  471 + break;
  472 + }
  473 + }
  474 + return results;
  475 + }
  476 +
  477 +
  478 +
431 } 479 }
  1 +package com.yoho.search.service.scene.searchlike;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.yoho.search.aop.cache.SearchCacheAble;
  5 +import com.yoho.search.base.utils.ProductIndexEsField;
  6 +import com.yoho.search.base.utils.SearchCollectionUtils;
  7 +import com.yoho.search.bo.BigdataSimilarSknIndexBO;
  8 +import com.yoho.search.common.SearchRequestParams;
  9 +import com.yoho.search.core.es.model.SearchParam;
  10 +import com.yoho.search.dal.model.BigdataSimilarSkn;
  11 +import com.yoho.search.models.SearchApiResult;
  12 +import com.yoho.search.service.helper.ProductListHelper;
  13 +import com.yoho.search.service.index.BigdataSimilarSknIndexBaseService;
  14 +import com.yoho.search.service.index.ProductIndexBaseService;
  15 +import org.apache.commons.lang.StringUtils;
  16 +import org.elasticsearch.index.query.BoolQueryBuilder;
  17 +import org.elasticsearch.index.query.QueryBuilder;
  18 +import org.elasticsearch.index.query.QueryBuilders;
  19 +import org.slf4j.Logger;
  20 +import org.slf4j.LoggerFactory;
  21 +import org.springframework.beans.factory.annotation.Autowired;
  22 +import org.springframework.stereotype.Service;
  23 +
  24 +import java.util.ArrayList;
  25 +import java.util.Arrays;
  26 +import java.util.List;
  27 +import java.util.Map;
  28 +
  29 +@Service
  30 +public class SearchLikeNotInShopService {
  31 +
  32 + private static final Logger logger = LoggerFactory.getLogger(SearchLikeNotInShopService.class);
  33 +
  34 + @Autowired
  35 + private SearchLikeHelper searchLikeHelper;
  36 + @Autowired
  37 + private ProductIndexBaseService productIndexBaseService;
  38 + @Autowired
  39 + private ProductListHelper productListHelper;
  40 + @Autowired
  41 + private BigdataSimilarSknIndexBaseService bigdataSimilarSknIndexBaseService;
  42 +
  43 + @SearchCacheAble(cacheInMinute = 600, cacheName = "SEARCH_LIKE_NOT_IN_SHOP_SIMILAR_NEW", includeParams = {"product_skn"})
  44 + public SearchApiResult searchLikeSimilarSknNotInShop(Map<String, String> paramMap) {
  45 + try {
  46 + // 1、获取参数
  47 + String productSkn = paramMap.get(SearchRequestParams.PARAM_SEARCH_PRODUCT_SKN);
  48 + if (StringUtils.isBlank(productSkn)) {
  49 + return new SearchApiResult().setCode(400).setMessage("请输入SKN");
  50 + }
  51 + // 2、检测分页参数【默认30条,最多60条】
  52 + int pageSize = 30;
  53 + // 3、获取当前查询的SKN的基本信息
  54 + JSONObject productInfoInEs = searchLikeHelper.getProductInfoInEs(productSkn);
  55 + if (productInfoInEs == null) {
  56 + return new SearchApiResult().setCode(400).setMessage("SKN不存在");
  57 + }
  58 + //4、获取similarskn
  59 + BigdataSimilarSknIndexBO bigdataSimilarSkn = bigdataSimilarSknIndexBaseService.querySimilarSkn(productSkn);
  60 +
  61 + //5、构造searchParams
  62 + List<SearchParam> searchParams = new ArrayList<>();
  63 + //5.1)图片[性别+不同店铺]
  64 + List<String> diffShopImgSimilarSkns = new ArrayList<>();
  65 + if (bigdataSimilarSkn != null && StringUtils.isNotEmpty(bigdataSimilarSkn.getDiffShopImgSimilarSkns())) {
  66 + diffShopImgSimilarSkns = searchLikeHelper.getDistinctSknList(bigdataSimilarSkn.getDiffShopImgSimilarSkns());
  67 + }
  68 + searchParams.add(this.builderSimilarSknSearchParam(productInfoInEs, diffShopImgSimilarSkns));
  69 +
  70 + //5.2)行为[性别+不同店铺+同品类]
  71 + List<String> diffShopActionSimilarSkns = new ArrayList<>();
  72 + if (bigdataSimilarSkn != null && StringUtils.isNotEmpty(bigdataSimilarSkn.getDiffShopActionSimilarSkns())) {
  73 + diffShopActionSimilarSkns = searchLikeHelper.getDistinctSknList(bigdataSimilarSkn.getDiffShopActionSimilarSkns());
  74 + }
  75 + searchParams.add(this.builderSimilarSknSearchParam(productInfoInEs, diffShopActionSimilarSkns));
  76 +
  77 + //5.3)文字兜底[性别+不同店铺+文字相似性]
  78 + searchParams.add(searchLikeHelper.builderSearchLikeNotInShopCharactersSearchParam(productInfoInEs, Arrays.asList(productSkn), pageSize, true));
  79 +
  80 + // 6、获取搜索结果
  81 + List<List<Map<String, Object>>> queryResults = searchLikeHelper.queryProductLists(searchParams);
  82 +
  83 + // 7、处理图片和行为的顺序
  84 + List<Map<String, Object>> diffShopImgSimilarProducts = searchLikeHelper.sortProductList(queryResults.get(0), diffShopImgSimilarSkns, pageSize / 3);
  85 + List<Map<String, Object>> diffShopActionSimilarProducts = searchLikeHelper.sortProductList(queryResults.get(1), diffShopActionSimilarSkns, pageSize / 3);
  86 +
  87 + // 8、获取临时结果
  88 + List<Map<String, Object>> tempProductList = new ArrayList<>();
  89 + tempProductList.addAll(diffShopImgSimilarProducts);
  90 + tempProductList.addAll(diffShopActionSimilarProducts);
  91 + tempProductList.addAll(queryResults.get(2));
  92 + if (tempProductList.size() > pageSize) {
  93 + tempProductList = SearchCollectionUtils.safeSubList(tempProductList, 0, pageSize);
  94 + }
  95 + // 8.1 保留偶数
  96 + if (tempProductList.size() % 2 > 0) {
  97 + tempProductList = SearchCollectionUtils.safeSubList(tempProductList, 0, tempProductList.size() - 1);
  98 + }
  99 + // 9、构造真实返回结果
  100 + List<Map<String, Object>> productListResults = new ArrayList<>();
  101 + if (!tempProductList.isEmpty()) {
  102 + productListResults = productListHelper.buildReturnInfoByEsSourceList(tempProductList);
  103 + }
  104 + JSONObject result = new JSONObject();
  105 + result.put("product_info", searchLikeHelper.genProductInfoResult(productInfoInEs));
  106 + result.put("product_list", productListResults);
  107 + return new SearchApiResult().setData(result);
  108 + } catch (Exception e) {
  109 + logger.error(e.getMessage(), e);
  110 + return new SearchApiResult().setData(null).setMessage("searchLikeNotInShop Exception").setCode(500);
  111 + }
  112 + }
  113 +
  114 + /**
  115 + * 构建SimilarSknSearchParam[考虑productSkns为空的情况]
  116 + *
  117 + * @param productInfoInEs
  118 + * @param productSkns
  119 + * @return
  120 + */
  121 + private SearchParam builderSimilarSknSearchParam(JSONObject productInfoInEs, List<String> productSkns) {
  122 + // 1、设置SearchParam
  123 + SearchParam searchParam = new SearchParam();
  124 + // 2)设置query和filter
  125 + searchParam.setFiter(this.builderSimilarSknFilter(productInfoInEs, productSkns));
  126 + // 3、设置分页参数
  127 + searchParam.setOffset(0);
  128 + searchParam.setSize(productSkns.size());
  129 + // 4)设置返回的参数【节省带宽】
  130 + List<String> includeFields = productIndexBaseService.getProductIndexIncludeFields();
  131 + searchParam.setIncludeFields(includeFields);
  132 + return searchParam;
  133 + }
  134 +
  135 + private QueryBuilder builderSimilarSknFilter(JSONObject productInfoInEs, List<String> inProductSkns) {
  136 + String isGlobalInEs = productInfoInEs.getString(ProductIndexEsField.isGlobal);
  137 + boolean isGlobal = "Y".equalsIgnoreCase(isGlobalInEs);
  138 + BoolQueryBuilder boolFilter = searchLikeHelper.genDefaultSearchLikeFilter(null, isGlobal);
  139 + // 1)设置此SKN相关的性别过滤条件
  140 + String gender = productInfoInEs.getString(ProductIndexEsField.gender);
  141 + List<String> genderList = searchLikeHelper.getGenderInfo(gender);
  142 + if (genderList != null && !genderList.isEmpty()) {
  143 + boolFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.gender, genderList));
  144 + }
  145 + // 2)设置productskn
  146 + if (inProductSkns != null && !inProductSkns.isEmpty()) {
  147 + boolFilter.must(QueryBuilders.termsQuery(ProductIndexEsField.productSkn, inProductSkns));
  148 + }
  149 + // 3)设置品牌或店铺信息
  150 + Integer brandId = productInfoInEs.getInteger(ProductIndexEsField.brandId);
  151 + Integer shopId = productInfoInEs.getInteger(ProductIndexEsField.shopId);
  152 + if (searchLikeHelper.isLegalInteger(shopId)) {
  153 + boolFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.shopId, shopId));
  154 + } else if (searchLikeHelper.isLegalInteger(brandId)) {
  155 + boolFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.brandId, brandId));
  156 + }
  157 + // 4)是否需要同品类
  158 + Integer middleSortId = productInfoInEs.getInteger(ProductIndexEsField.middleSortId);
  159 + if (searchLikeHelper.isLegalInteger(middleSortId)) {
  160 + boolFilter.must(QueryBuilders.termQuery(ProductIndexEsField.middleSortId, middleSortId));
  161 + }
  162 + return boolFilter;
  163 + }
  164 +
  165 +}