Authored by 胡古飞

索引中加入实时计算的断码率

1 package com.yoho.search.dal.model; 1 package com.yoho.search.dal.model;
2 2
3 -  
4 /** 3 /**
5 * Created by wangnan on 2016/6/30. 4 * Created by wangnan on 2016/6/30.
6 */ 5 */
@@ -9,6 +8,7 @@ public class ProductSizes { @@ -9,6 +8,7 @@ public class ProductSizes {
9 private String sizeIds; 8 private String sizeIds;
10 private String sizeNames; 9 private String sizeNames;
11 private Integer storageNum; 10 private Integer storageNum;
  11 + private double breakSizePercent = 100;
12 12
13 public Integer getProductId() { 13 public Integer getProductId() {
14 return productId; 14 return productId;
@@ -41,4 +41,13 @@ public class ProductSizes { @@ -41,4 +41,13 @@ public class ProductSizes {
41 public void setSizeNames(String sizeNames) { 41 public void setSizeNames(String sizeNames) {
42 this.sizeNames = sizeNames; 42 this.sizeNames = sizeNames;
43 } 43 }
  44 +
  45 + public double getBreakSizePercent() {
  46 + return breakSizePercent;
  47 + }
  48 +
  49 + public void setBreakSizePercent(double breakSizePercent) {
  50 + this.breakSizePercent = breakSizePercent;
  51 + }
  52 +
44 } 53 }
@@ -39,13 +39,19 @@ public abstract class AbstractStorageRelatedMqListener extends AbstractMqListene @@ -39,13 +39,19 @@ public abstract class AbstractStorageRelatedMqListener extends AbstractMqListene
39 39
40 protected void fillStorageNumAndSizeInfo(Integer productId, Map<String, Object> indexData) { 40 protected void fillStorageNumAndSizeInfo(Integer productId, Map<String, Object> indexData) {
41 List<Storage> storageList = storageService.getStoragesByProductId(productId); 41 List<Storage> storageList = storageService.getStoragesByProductId(productId);
  42 + // 过滤掉下架的storage
42 if (CollectionUtils.isNotEmpty(storageList)) { 43 if (CollectionUtils.isNotEmpty(storageList)) {
43 - // 过滤掉下架的无库存的storage  
44 - storageList = storageList.stream()  
45 - .filter(storage -> Integer.valueOf(1).equals(storage.getStatus()))  
46 - .filter(storage -> storage.getStorageNum() != null && storage.getStorageNum().intValue() > 0)  
47 - .collect(Collectors.toList()); 44 + storageList = storageList.stream().filter(storage -> Integer.valueOf(1).equals(storage.getStatus())).collect(Collectors.toList());
48 } 45 }
  46 + int totalSizeCount = storageList.size();
  47 +
  48 + // 过滤掉无库存的storage
  49 + if (CollectionUtils.isNotEmpty(storageList)) {
  50 + storageList = storageList.stream().filter(storage -> storage.getStorageNum() != null && storage.getStorageNum().intValue() > 0).collect(Collectors.toList());
  51 + }
  52 + int effectiveSizeCount = storageList.size();
  53 +
  54 + float breakSizePercent = 100 * (totalSizeCount - effectiveSizeCount)/totalSizeCount;
49 55
50 if (CollectionUtils.isEmpty(storageList)) { 56 if (CollectionUtils.isEmpty(storageList)) {
51 indexData.put("storageNum", 0); 57 indexData.put("storageNum", 0);
@@ -53,6 +59,7 @@ public abstract class AbstractStorageRelatedMqListener extends AbstractMqListene @@ -53,6 +59,7 @@ public abstract class AbstractStorageRelatedMqListener extends AbstractMqListene
53 indexData.put("isSoldOut", "Y"); 59 indexData.put("isSoldOut", "Y");
54 indexData.put("soldOut", 0); 60 indexData.put("soldOut", 0);
55 indexData.put("sizeIds", null); 61 indexData.put("sizeIds", null);
  62 + indexData.put("breakSizePercent", 100);
56 } else { 63 } else {
57 int storageNum = 0; 64 int storageNum = 0;
58 Set<String> sizeSet = new HashSet<String>(); 65 Set<String> sizeSet = new HashSet<String>();
@@ -74,6 +81,7 @@ public abstract class AbstractStorageRelatedMqListener extends AbstractMqListene @@ -74,6 +81,7 @@ public abstract class AbstractStorageRelatedMqListener extends AbstractMqListene
74 indexData.put("sizeIds", null); 81 indexData.put("sizeIds", null);
75 indexData.put("sizeNames", null); 82 indexData.put("sizeNames", null);
76 } 83 }
  84 + indexData.put("breakSizePercent", breakSizePercent);
77 } 85 }
78 } 86 }
79 87
@@ -87,7 +95,7 @@ public abstract class AbstractStorageRelatedMqListener extends AbstractMqListene @@ -87,7 +95,7 @@ public abstract class AbstractStorageRelatedMqListener extends AbstractMqListene
87 ProductGoodsBO productGoodsBO = productGoodsBOList.get(0); 95 ProductGoodsBO productGoodsBO = productGoodsBOList.get(0);
88 String goodsListJsonArrayStr = productGoodsBO.getGoodsList(); 96 String goodsListJsonArrayStr = productGoodsBO.getGoodsList();
89 JSONArray goodsListJsonArray = JSONArray.parseArray(goodsListJsonArrayStr); 97 JSONArray goodsListJsonArray = JSONArray.parseArray(goodsListJsonArrayStr);
90 - productGoodsLogicService.getColorSet(goodsListJsonArray, colorIdSet, colorNameSet);//获取有库存且状态正常的color 98 + productGoodsLogicService.getColorSet(goodsListJsonArray, colorIdSet, colorNameSet);// 获取有库存且状态正常的color
91 indexData.put("goodsList", goodsListJsonArray); 99 indexData.put("goodsList", goodsListJsonArray);
92 indexData.put("colorIds", StringUtils.join(colorIdSet, ",")); 100 indexData.put("colorIds", StringUtils.join(colorIdSet, ","));
93 indexData.put("colorNames", StringUtils.join(colorNameSet, ",")); 101 indexData.put("colorNames", StringUtils.join(colorNameSet, ","));
@@ -781,6 +781,9 @@ @@ -781,6 +781,9 @@
781 "type": "string", 781 "type": "string",
782 "analyzer": "comma_spliter" 782 "analyzer": "comma_spliter"
783 }, 783 },
  784 + "breakSizePercent": {
  785 + "type": "double"
  786 + },
784 "standardIds": { 787 "standardIds": {
785 "type": "string", 788 "type": "string",
786 "analyzer": "comma_spliter" 789 "analyzer": "comma_spliter"
@@ -126,6 +126,8 @@ public class ProductIndexService { @@ -126,6 +126,8 @@ public class ProductIndexService {
126 map.put(ProductIndexEsField.colorNames, productIndexBO.getColorNames()); 126 map.put(ProductIndexEsField.colorNames, productIndexBO.getColorNames());
127 map.put(ProductIndexEsField.sizeIds, productIndexBO.getSizeIds()); 127 map.put(ProductIndexEsField.sizeIds, productIndexBO.getSizeIds());
128 map.put(ProductIndexEsField.sizeNames, productIndexBO.getSizeNames()); 128 map.put(ProductIndexEsField.sizeNames, productIndexBO.getSizeNames());
  129 + map.put(ProductIndexEsField.breakSizePercent, productIndexBO.getBreakSizePercent());
  130 +
129 map.put(ProductIndexEsField.standardIds, productIndexBO.getStandardIds()); 131 map.put(ProductIndexEsField.standardIds, productIndexBO.getStandardIds());
130 map.put(ProductIndexEsField.standardNames, productIndexBO.getStandardNames()); 132 map.put(ProductIndexEsField.standardNames, productIndexBO.getStandardNames());
131 map.put(ProductIndexEsField.styleIds, productIndexBO.getStyleIds()); 133 map.put(ProductIndexEsField.styleIds, productIndexBO.getStyleIds());
@@ -53,6 +53,7 @@ public class ProductIndexBO extends ProductIBO implements Serializable { @@ -53,6 +53,7 @@ public class ProductIndexBO extends ProductIBO implements Serializable {
53 private Integer soldOut; 53 private Integer soldOut;
54 private String sizeIds; 54 private String sizeIds;
55 private String sizeNames; 55 private String sizeNames;
  56 + private double breakSizePercent;
56 57
57 // from product_15day_salesnum 58 // from product_15day_salesnum
58 private Integer salesNum; 59 private Integer salesNum;
@@ -416,6 +417,14 @@ public class ProductIndexBO extends ProductIBO implements Serializable { @@ -416,6 +417,14 @@ public class ProductIndexBO extends ProductIBO implements Serializable {
416 return sizeNames; 417 return sizeNames;
417 } 418 }
418 419
  420 + public double getBreakSizePercent() {
  421 + return breakSizePercent;
  422 + }
  423 +
  424 + public void setBreakSizePercent(double breakSizePercent) {
  425 + this.breakSizePercent = breakSizePercent;
  426 + }
  427 +
419 public String getIsStudentPrice() { 428 public String getIsStudentPrice() {
420 return isStudentPrice; 429 return isStudentPrice;
421 } 430 }
@@ -8,6 +8,7 @@ import com.yoho.search.dal.model.Goods; @@ -8,6 +8,7 @@ import com.yoho.search.dal.model.Goods;
8 import com.yoho.search.dal.model.ProductSizes; 8 import com.yoho.search.dal.model.ProductSizes;
9 import com.yoho.search.dal.model.Size; 9 import com.yoho.search.dal.model.Size;
10 import com.yoho.search.dal.model.Storage; 10 import com.yoho.search.dal.model.Storage;
  11 +
11 import org.apache.commons.collections.CollectionUtils; 12 import org.apache.commons.collections.CollectionUtils;
12 import org.springframework.beans.factory.annotation.Autowired; 13 import org.springframework.beans.factory.annotation.Autowired;
13 import org.springframework.stereotype.Component; 14 import org.springframework.stereotype.Component;
@@ -37,26 +38,38 @@ public class ProductSizesLogicService { @@ -37,26 +38,38 @@ public class ProductSizesLogicService {
37 38
38 /** 39 /**
39 * 获取ProductSizes列表 40 * 获取ProductSizes列表
  41 + *
40 * @return 42 * @return
41 */ 43 */
42 public List<ProductSizes> getData(List<Integer> ids) { 44 public List<ProductSizes> getData(List<Integer> ids) {
43 - //获取ProductId对应的上架的goodsId列表 45 + // 获取ProductId对应的上架的goodsId列表
44 List<Goods> goodsList = goodsMapper.getByIdsAndStatus(ids); 46 List<Goods> goodsList = goodsMapper.getByIdsAndStatus(ids);
45 - if(CollectionUtils.isEmpty(goodsList)){ 47 + if (CollectionUtils.isEmpty(goodsList)) {
46 return new ArrayList<>(); 48 return new ArrayList<>();
47 } 49 }
48 50
49 - //获取goodsId对应得Storage列表 51 + // 获取goodsId对应得Storage列表
50 List<Integer> goodsIdList = goodsList.parallelStream().map(Goods::getId).collect(Collectors.toList()); 52 List<Integer> goodsIdList = goodsList.parallelStream().map(Goods::getId).collect(Collectors.toList());
51 List<Storage> storageList = storageMapper.getByGoodsIds(goodsIdList); 53 List<Storage> storageList = storageMapper.getByGoodsIds(goodsIdList);
52 if (CollectionUtils.isEmpty(storageList)) { 54 if (CollectionUtils.isEmpty(storageList)) {
53 return new ArrayList<>(); 55 return new ArrayList<>();
54 } 56 }
55 57
56 - //过滤状态是上架的且有库存的Goods和Storage  
57 - storageList = storageList.parallelStream().filter(storageItem -> VALID_STATUS.equals(storageItem.getStatus()))  
58 - .filter(storageItem -> storageItem.getStorageNum() != null && storageItem.getStorageNum().intValue() > 0).collect(Collectors.toList());  
59 - if(CollectionUtils.isEmpty(storageList)){ 58 + // 过滤掉下架的sku
  59 + storageList = storageList.parallelStream().filter(storageItem -> VALID_STATUS.equals(storageItem.getStatus())).collect(Collectors.toList());
  60 +
  61 + // 计算每个skn则总尺码数
  62 + Map<Integer, Integer> sknSizeCountMap = new HashMap<Integer, Integer>();
  63 + for (Storage storage : storageList) {
  64 + Integer productId = storage.getProductId();
  65 + int count = sknSizeCountMap.getOrDefault(productId, 0);
  66 + sknSizeCountMap.put(productId, count + 1);
  67 + }
  68 +
  69 + // 过滤状态是上架的且有库存的Goods和Storage
  70 + storageList = storageList.parallelStream().filter(storageItem -> storageItem.getStorageNum() != null && storageItem.getStorageNum().intValue() > 0)
  71 + .collect(Collectors.toList());
  72 + if (CollectionUtils.isEmpty(storageList)) {
60 return new ArrayList<>(); 73 return new ArrayList<>();
61 } 74 }
62 75
@@ -68,8 +81,7 @@ public class ProductSizesLogicService { @@ -68,8 +81,7 @@ public class ProductSizesLogicService {
68 validErpSkuIdList.add(s.getErpSkuId()); 81 validErpSkuIdList.add(s.getErpSkuId());
69 } 82 }
70 } 83 }
71 -  
72 - //判断sku列表是否为空 84 + // 判断sku列表是否为空
73 if (validErpSkuIdList == null || validErpSkuIdList.isEmpty()) { 85 if (validErpSkuIdList == null || validErpSkuIdList.isEmpty()) {
74 return new ArrayList<>(); 86 return new ArrayList<>();
75 } 87 }
@@ -90,24 +102,38 @@ public class ProductSizesLogicService { @@ -90,24 +102,38 @@ public class ProductSizesLogicService {
90 } 102 }
91 } 103 }
92 104
  105 + // 获取尺码信息
93 List<Size> sizeList = sizeMapper.getByIds(sizeIdSet.stream().collect(Collectors.toList())); 106 List<Size> sizeList = sizeMapper.getByIds(sizeIdSet.stream().collect(Collectors.toList()));
  107 +
  108 + // 填充尺码信息和断码率
94 if (CollectionUtils.isNotEmpty(sizeList)) { 109 if (CollectionUtils.isNotEmpty(sizeList)) {
95 Map<Integer, String> sizeMap = sizeList.stream().collect(Collectors.toMap(Size::getId, Size::getSizeName)); 110 Map<Integer, String> sizeMap = sizeList.stream().collect(Collectors.toMap(Size::getId, Size::getSizeName));
96 - //productSizesList.forEach(ps -> ps.setSizeNames(Arrays.stream(ps.getSizeIds().split(",")).map(Integer::valueOf).map(sizeId -> sizeMap.get(sizeId)).collect(Collectors.joining(","))));  
97 for (ProductSizes ps : productSizesList) { 111 for (ProductSizes ps : productSizesList) {
98 String sizeArray[] = ps.getSizeIds().split(","); 112 String sizeArray[] = ps.getSizeIds().split(",");
  113 + // 计算断码率
  114 + double breakSizePercent = this.getBreakSizePercent(sknSizeCountMap.getOrDefault(ps.getProductId(), 0), sizeArray == null ? 0 : sizeArray.length);
  115 + ps.setBreakSizePercent(breakSizePercent);
  116 + // 填充尺码名称
99 if (sizeArray != null) { 117 if (sizeArray != null) {
100 for (int i = 0; i < sizeArray.length; i++) { 118 for (int i = 0; i < sizeArray.length; i++) {
101 if (i == 0) { 119 if (i == 0) {
102 - ps.setSizeNames(sizeMap.get(Integer.valueOf(sizeArray[i]))+ ","); 120 + ps.setSizeNames(sizeMap.get(Integer.valueOf(sizeArray[i])) + ",");
103 } else { 121 } else {
104 - ps.setSizeNames(ps.getSizeNames() + sizeMap.get(Integer.valueOf(sizeArray[i]))+ ","); 122 + ps.setSizeNames(ps.getSizeNames() + sizeMap.get(Integer.valueOf(sizeArray[i])) + ",");
105 } 123 }
106 } 124 }
  125 +
107 } 126 }
108 } 127 }
109 } 128 }
110 -  
111 return productSizesList; 129 return productSizesList;
112 } 130 }
  131 +
  132 + private double getBreakSizePercent(int totalSizeCount, int effectiveSizeCount) {
  133 + if (totalSizeCount == 0 || effectiveSizeCount == 0) {
  134 + return 100d;
  135 + }
  136 + return 100d * (effectiveSizeCount - totalSizeCount) / totalSizeCount;
  137 + }
  138 +
113 } 139 }
@@ -19,6 +19,7 @@ public class ProductSizesBuilder implements ViewBuilder { @@ -19,6 +19,7 @@ public class ProductSizesBuilder implements ViewBuilder {
19 19
20 @Autowired 20 @Autowired
21 private ProductSizesLogicService productSizesLogicService; 21 private ProductSizesLogicService productSizesLogicService;
  22 +
22 /** 23 /**
23 * 构建ProductSizes数据 24 * 构建ProductSizes数据
24 */ 25 */
@@ -31,6 +32,7 @@ public class ProductSizesBuilder implements ViewBuilder { @@ -31,6 +32,7 @@ public class ProductSizesBuilder implements ViewBuilder {
31 productIndexBO.setIsSoonSoldOut("N"); 32 productIndexBO.setIsSoonSoldOut("N");
32 productIndexBO.setIsSoldOut("N"); 33 productIndexBO.setIsSoldOut("N");
33 productIndexBO.setSoldOut(1); 34 productIndexBO.setSoldOut(1);
  35 + productIndexBO.setBreakSizePercent(100);
34 if (productSizes != null) { 36 if (productSizes != null) {
35 productIndexBO.setStorageNum(BigDecimal.valueOf(productSizes.getStorageNum())); 37 productIndexBO.setStorageNum(BigDecimal.valueOf(productSizes.getStorageNum()));
36 if (productSizes.getStorageNum() <= 2) { 38 if (productSizes.getStorageNum() <= 2) {
@@ -42,11 +44,12 @@ public class ProductSizesBuilder implements ViewBuilder { @@ -42,11 +44,12 @@ public class ProductSizesBuilder implements ViewBuilder {
42 } 44 }
43 productIndexBO.setSizeIds(productSizes.getSizeIds()); 45 productIndexBO.setSizeIds(productSizes.getSizeIds());
44 productIndexBO.setSizeNames(productSizes.getSizeNames()); 46 productIndexBO.setSizeNames(productSizes.getSizeNames());
45 - }  
46 - else { 47 + productIndexBO.setBreakSizePercent(productSizes.getBreakSizePercent());
  48 + } else {
47 productIndexBO.setStorageNum(BigDecimal.valueOf(0)); 49 productIndexBO.setStorageNum(BigDecimal.valueOf(0));
48 productIndexBO.setIsSoldOut("Y"); 50 productIndexBO.setIsSoldOut("Y");
49 productIndexBO.setSoldOut(0); 51 productIndexBO.setSoldOut(0);
  52 + productIndexBO.setBreakSizePercent(100);
50 } 53 }
51 } 54 }
52 } 55 }