谷粒商城实现商品的上架(数据整合迁移到ES)

写这个文章主要是为了梳理业务,理清思路。
1.定义我们上传产品的映射
在这里插入图片描述这是我们对上传产品的映射信息,主要是sku表的信息和attr属性表的信息。
attrs的类型是嵌套。属性表查得信息必须是可以检索的,比如我们可以在京东的搜索页面,通过选择cpu的型号进行搜索匹配。
然后热点值hitscore以后完善。然后需要查询我们是否具有库存hasStock,通过各种数据的处理来进行封装。
2 定义映射对象


@Data
/**
 * 本质上传输对象  实际上在product和搜索微服务都应该有该对象
 */
public class SkuEsModel {
    private Long skuId;
    private Long spuId;
    private String skuTitle;
    private BigDecimal skuPrice;
    private String skuImg;
    private Long saleCount;
    private Boolean hasStock;
    private Long hotScore;
    private Long brandId;
    private Long catalogId;
    private String brandName;
    private String brandImg;
    private String catalogName;
    private List<Attrs> attrs;
    //检索属性
    @Data
    public static class Attrs {
        private Long attrId;
        private String attrName;
        private String attrValue;
    }
}

3业务实现
3.1编写上架接口,传入spuId

 /**
     * 实现商品上架
     */
    @PostMapping("{spuId}/up")
    public R spuUp(@PathVariable("spuId") Long spuId) {
        spuInfoService.spuUp(spuId);
        return R.ok();
    }

3.2对service层数据进行处理封装
3.2.1 第一步根据spuId查出所有的sku信息

List<SkuInfoEntity> skus = skuInfoService.getSkuBySpuId(spuId);

3.2 .2查询sku可以被检索的规格属性
controller层
根据spuId查出在产品属性表的属性id的集合,封装为set

    List<ProductAttrValueEntity> baseAttrs = attrValueService.baseAttrList(spuId);
        List<Long> attrIds = baseAttrs.stream().map(productAttrValueEntity -> {
            return productAttrValueEntity.getAttrId();
        }).collect(Collectors.toList());

根据返回的属性ld的集合,查找属性,而且是可以被检索的索性,返回值存入set集合中,方便以后进行校验

<select id="selectSearchAttrs" resultType="java.lang.Long">
        select * from pms_attr
        where attr_id in
            <foreach collection="attrIds" item="id" separator="," open="(" close=")">#{id}</foreach>
        and search_type=1
    </select>

然后把数据封装到attrs中,对于任何一个spu来讲,他的attrs都是相同的。

 //把数据封装attrs
        List<SkuEsModel.Attrs> attrsList = baseAttrs.stream().filter(productAttrValueEntity -> {
            return set.contains(productAttrValueEntity.getAttrId());
        }).map(productAttrValueEntity -> {
            SkuEsModel.Attrs attrs = new SkuEsModel.Attrs();
            BeanUtils.copyProperties(productAttrValueEntity, attrs);
            return attrs;
        }).collect(Collectors.toList());

3.2.3 对库存数据进行查询,由于使用stream流每次根据spu查询会比较繁琐,消耗性能,我们把库存统一查询。首先或许所有的skuId的集合,最后封装为kv map形式的数据。方便数据传输,专门做了vo类。

public class SkuHasStockVo {

    private Long skuId;

    private boolean hasStock; //是否有库存
}

在fegin调用查询数据是,注意返回的类型包装,R类型继承hashmap,需要我们根据类 TypeReference进行处理(阿里提供),利用json进行复杂类型的转换,仅仅依靠泛型是无法转换的,我们的数据类型是List

/**
	 * @param key 获取指定key的名字
	 */
	public <T> T getData(String key, TypeReference<T> typeReference){
		// get("data") 默认是map类型 所以再由map转成string再转json
		Object data = get(key);
		return JSON.parseObject(JSON.toJSONString(data), typeReference);
	}
	/**
	 * 复杂类型转换 TypeReference
	 * @param typeReference
	 */
	public <T> T getData(TypeReference<T> typeReference){
		// get("data") 默认是map类型 所以再由map转成string再转json
		Object data = get("data");
		String s = JSON.toJSONString(data);
		T t = JSON.parseObject(s, typeReference);
		return t;
	}

fegin调用service时的封装
在这里插入图片描述
最后就是我们取到数据,转换传入类型转换为map格式,我们通过key(skuId)就可以查到值是否有库存

List<Long> skuIds = skus.stream().map(sku -> {
            return sku.getSkuId();
        }).collect(Collectors.toList());

        Map<Long, Boolean> stockMap=null;
        try {
            R  r = wareFeginService.getSkusHasStocks(skuIds);
            TypeReference<List<SkuHasStockVo>> typeReference = new TypeReference<List<SkuHasStockVo>>() {
            };
            stockMap = r.getData(typeReference).stream().collect(Collectors.toMap(SkuHasStockVo::getSkuId, skuHasStockVo -> skuHasStockVo.isHasStock()));
            log.warn("服务调用成功" + typeReference);
        } catch (Exception e) {
            log.error("网络抖动查不到库存数据{}"+e);
        }

4数据封装,传递给es上架,实现数据迁移

List<SkuEsModel> upProducts = skus.stream().map(sku -> {
            //组装需要的数据
            SkuEsModel skuEsModel = new SkuEsModel();
            BeanUtils.copyProperties(sku, skuEsModel);
            //skuPrice,skuImg,hotscore
            skuEsModel.setSkuPrice(sku.getPrice());
            skuEsModel.setSkuImg(sku.getSkuDefaultImg());
            //查询是否还有库存
            if(finalStockMap ==null){
                skuEsModel.setHasStock(true);
            }else{
                skuEsModel.setHasStock(finalStockMap.get(sku.getSkuId()));
            }
            //TODO 2 热度评分
             skuEsModel.setHotScore( 0l);
            //品牌名字  分类名字
            BrandEntity brandEntity = brandService.getById(skuEsModel.getBrandId());
            skuEsModel.setBrandName(brandEntity.getName());
            skuEsModel.setBrandImg(brandEntity.getLogo());
            categoryService.getById(skuEsModel.getCatalogId());
            //设置检索属性
            skuEsModel.setAttrs(attrsList);
            return skuEsModel;
        }).collect(Collectors.toList());

装好数据调用搜索服务上架,上架成功就要修改spu的状态,新建转为上架状态。
这是搜索的服务层

 R r = searchFeginService.startProduct(upProducts);

        if(r.getCode()==0){
            //商品上架成功
            //修改spu的状态
            baseMapper.updateSpuStatus(spuId,ProductConstant.StatusEnum.UP_SPU.getCode());
        }else{
`` //2 给es保存这些数据
        BulkRequest bulkRequest = new BulkRequest();
        for (SkuEsModel skuEsModel : skuEsModels) {
            IndexRequest indexRequest = new IndexRequest(EsConstant.PRODUCT_INDEX);
            indexRequest.id(skuEsModel.getSkuId().toString());
            String s = JSON.toJSONString(skuEsModel);
            indexRequest.source(s,XContentType.JSON);
            bulkRequest.add(indexRequest);
        }
        BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, GulimailESConfig.COMMON_OPTIONS);
        //如果出现上传错误 TODO
        boolean hasFailures = bulk.hasFailures();
        List<String> ids = Arrays.stream(bulk.getItems()).map(item -> {
                    return item.getId();
                }
        ).collect(Collectors.toList());
        log.error("商品上传{}  状态"+ids+bulk.toString());
        return hasFailures;
    }
    

controller层

@PostMapping("/product")
    public R startProduct(@RequestBody List<SkuEsModel> skuEsModels) {
        boolean b=false;
        try {
            b = productSaveService.startProduct(skuEsModels);
        } catch (IOException e) {
            log.error("ElasticSaveController商品上传出现异常",e);
           return R.error(BizCodeEnume.PRODUCT_UP_EXCEPTION.getCode(),BizCodeEnume.PRODUCT_UP_EXCEPTION.getMessage());
        }
        if(!b){return R.ok();}else { return R.error(BizCodeEnume.PRODUCT_UP_EXCEPTION.getCode(),BizCodeEnume.PRODUCT_UP_EXCEPTION.getMessage());}
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值