谷粒商城项目:功能业务逻辑(上架)

1.上架功能

1.1 业务逻辑

商品数据—》保存到ElasticSearch—》可以被检索到

1.2 商品数据保存到ElasticSearch的理由
  • 内存运算
  • 检索性能强大
  • 可以分片存放数据
1.3 常见的保存到ElasticSearch的数据格式
格式一:
                  {
						skuId:1
						spuId:1
						skuTitle:小米
						price:1000
						saleCount:999
						attrs[
							{尺寸:1寸}{CPU:麒麟996}{分辨率:高清}
						]
					}

产生的问题:冗余字段(空间换时间)

格式二:
                   {
						skuId:1
						spuId:1
					}
					attr索引{
							spuId:1,
							attrs[
								{尺寸:1寸}{CPU:麒麟996}{分辨率:高清}
							]
					}
					

产生的问题:并发高的情况下,传输的数据过大(时间换空间)

1.4 本项目所采用的格式
                 {
					"mappings":{
						"properties":{
							"skuId":{
								"type":"long"
							},
							"spuId":{
								"type":"keyword"
							},
							"skuTitle":{
								"type":"text",
								"analyzer":"ik_smart" //使用ik分词器进行检索
							},
							"skuPrice":{
								"type":"keyword"
							},
							"skuImg":{
								"type":"keyword",
								"index":false,  //默认为true,false表示不参与检索
								"doc_values":false   //默认为true,false表示不参与聚合
							},
							"skuCount":{
								"type":"long"
							},
							"hasStock":{  //是否有库存
								"type":"boolean"
							},
							"hotScore":{  //热度计算
								"type":"long"
							},
							"brandId":{  //品牌id
								"type":"long"
							},
							"categoryId":{  //分类id
								"type":"long"
							},
							"brandName":{  //品牌名字
								"type":"keyword",
								"index":false,  //默认为true,false表示不参与检索
								"doc_values":false   //默认为true,false表示不参与聚合
							},
							"brandImg":{  //品牌图片
								"type":"keyword",
								"index":false,  //默认为true,false表示不参与检索
								"doc_values":false   //默认为true,false表示不参与聚合
							},
							"categoryName":{  //分类名字
								"type":"keyword",
								"index":false,  //默认为true,false表示不参与检索
								"doc_values":false   //默认为true,false表示不参与聚合
							},
							"attrs":{  //属性集合
								"type":"nested",  //嵌入式,表示该字段内部属性参与检索和聚合
								"properties":{
									"attrId":{
										"type":"long"
									},
									"attrName":{
										"type":"keyword",
										"index":false,  //默认为true,false表示不参与检索
										"doc_values":false   //默认为true,false表示不参与聚合
									},
									"attrValue":{
										"type":"keyword"
									}
								}
							}
							
						}
					}
				}
1.5 代码逻辑
  1. 查出当前spuId对应的所有sku信息,品牌的名字
  2. 封装每个sku的信息
  3. 发送远程调用,向库存系统查询是否有库存
  4. 热度评分计算
  5. 查询品牌和分类的名字信息
  6. 查询当前sku所有可以被用来检索的规格属性
  7. 将数据发送给es进行保存
public void up(Long spuId) {

        //1.查出当前spuId对应的所有sku信息,品牌的名字
        List<SkuInfoEntity> skus = skuInfoService.getSkusBySpuId(spuId);

        List<Long> skuIdList = skus.stream().map(
                SkuInfoEntity::getSkuId
        ).collect(Collectors.toList());



        //2.4 查询当前sku所有可以被用来检索的规格属性
        //baseAttrs:当前spu下的所有属性的集合
        //searchAttrIds:可以被检索到的属性
        //处理逻辑:在baseAttrs筛选出可以被检索的属性
        List<ProductAttrValueEntity> baseAttrs = attrValueService.baseAttrlistforspu(spuId);
        List<Long> attrIds = baseAttrs.stream().map((attr) -> {
            return attr.getAttrId();
        }).collect(Collectors.toList());

        //在指定的所有属性集合里面,选出可以被检索的属性
        List<Long> searchAttrIds = attrService.selectSearchAttrs(attrIds);

        HashSet<Long> idSet = new HashSet<>(searchAttrIds);

        List<SkuEsModel.Attrs> attrsList = baseAttrs.stream().filter((item) -> {
            //在baseAttrs筛选出可以被检索的属性,即baseAttrs的元素的id是否在idSet里面
            return idSet.contains(item.getAttrId());
        }).map((item) -> {
            SkuEsModel.Attrs attrs = new SkuEsModel.Attrs();
            BeanUtils.copyProperties(item, attrs);
            return attrs;
        }).collect(Collectors.toList());

        //2.1 发送远程调用,向库存系统查询是否有库存

        Map<Long, Boolean> stockMap = null;
        try {
            R r = wareFeignService.getSkusHasStock(skuIdList);
            TypeReference typeReference = new TypeReference<List<SkuHasStockVo>>() {
            };
            List<SkuHasStockVo> data = (List<SkuHasStockVo>) r.getData(typeReference);
            stockMap = data.stream().collect(Collectors.toMap(SkuHasStockVo::getSkuId, (item) -> {
                return item.getHasStock();
            }));
        } catch (Exception e) {
           log.error("库存服务查询异常:原因{}",e);
        }

        //2.封装每个sku的信息
        Map<Long, Boolean> finalStockMap = stockMap;
        List<SkuEsModel> upProducts = skus.stream().map((sku) -> {
            //组装需要的数据
            SkuEsModel esModel = new SkuEsModel();
            BeanUtils.copyProperties(sku, esModel);
            //处理sku和esModel不同的字段
            //sku和esModel名字不同的字段:SkuImg,SkuPrice
            esModel.setSkuImg(sku.getSkuDefaultImg());
            esModel.setSkuPrice(sku.getPrice());
            //sku未有的字段:hasStock,hotScore
            //2.1 发送远程调用,向库存系统查询是否有库存
            if (finalStockMap == null){
                esModel.setHasStock(true);
            }else {
                esModel.setHasStock(finalStockMap.get(sku.getSkuId()));
            }

            //TODO 2.2 热度评分计算
            esModel.setHotScore(0L);

            //2.3 查询品牌和分类的名字信息
            BrandEntity brand = brandService.getById(sku.getBrandId());
            esModel.setBrandImg(brand.getLogo());
            esModel.setBrandName(brand.getName());

            CategoryEntity category = categoryService.getById(esModel.getCatalogId());
            esModel.setCatalogName(category.getName());

            //2.4 查询当前sku所有可以被用来检索的规格属性
            esModel.setAttrs(attrsList);

            return esModel;
        }).collect(Collectors.toList());

        //3 将数据发送给es进行保存
        R result = searchFeignService.productStatusUp(upProducts);
        if (result.getCode() == 0){
            //远程调用成功
            //修改当前spu的状态,改为已上架
            baseMapper.updateStatus(spuId, ProductConstant.StatusEnum.SPU_UP.getCode());
        }else {
            //远程调用失败
            //TODO 产生的问题:重复调用,接口幂等性
        }
    }
1.6 Feign调用流程

1.构造请求数据,将对象转为JSON

 RequestTemplate template = buildTemplateFromArgs.create(argv)

2.发送请求进行执行(执行成功会进行解码响应数据)

 executeAndDecode(template)

3.执行请求会有重试机制

          whiletrue{
                            try{
                                executeAndDecode(template)
                            }catch(){
                            try{retryer.continueOrPropagate(e);}catch(){
                            }
                            continue}
                        }
1.7 产生的问题
重复调用
接口幂等性
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值