商品上架:构造基本数据


package com.atguigu.common.to.es;

import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;

/**
 * 

Title: SkuEsModel

* Description: * "mappings": { * "properties": { * "skuId":{ * "type": "long" * }, * "spuId":{ * "type": "keyword" * }, * "skuTitle":{ * "type": "text", * "analyzer": "ik_smart" * }, * "skuPrice":{ * "type": "keyword" * }, * "skuImg":{ * "type": "keyword", * "index": false, * "doc_values": false * }, * "saleCount":{ * "type": "long" * }, * "hasStock":{ * "type": "boolean" * }, * "hotScore":{ * "type": "long" * }, * "brandId":{ * "type": "long" * }, * "catalogId":{ * "type": "long" * }, * "brandName":{ * "type":"keyword", * "index": false, * "doc_values": false * }, * "brandImg":{ * "type": "keyword", * "index": false, * "doc_values": false * }, * "catalogName":{ * "type": "keyword", * "index": false, * "doc_values": false * }, * "attrs":{ * "type": "nested", * "properties": { * "attrId":{ * "type":"long" * }, * "attrName":{ * "type":"keyword", * "index":false, * "doc_values": false * }, * "attrValue":{ * "type":"keyword" * } * } * } * } * } * date:2020/6/8 18:52 */ @Data public class SkuEsModel implements Serializable { 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; /** * 检索属性 */ @Data public static class Attrs implements Serializable{ private Long attrId; private String attrName; private String attrValue; } }

 讲道理,这个应该放到product服务和search服务中,这里放到了common服务中。

再次理清 skuspu:

===================================

    /**
     * 不一样的属性:skuPrice、skuImg、hasStock、hotScore、
     * brandName、brandImg、catalogName、attrs
     *
     * @param spuId
     */
    @Override
    public void up(Long spuId) {
        // 1 组装数据 查出当前spuId对应的所有sku信息
        List skus = skuInfoService.getSkusBySpuId(spuId);
        // TODO  4. 查询当前 SKU的所有 可以被用来检索的规格属性===这些规格属性是按照spu来的,所以放到外面查一遍即可

        // 2 封装每个sku的信息
        List uoProducts = skus.stream().map((x) -> {
            SkuEsModel esModel = new SkuEsModel();
            //一样的属性:
            BeanUtils.copyProperties(x,esModel);//这个是spring的类 把当前遍历的sku拷贝到esModel中

//不一样的属性:skuPrice、skuImg、hasStock、hotScore、brandName、brandImg、catalogName、attrs
            //skuPrice、skuImg
            esModel.setSkuPrice(x.getPrice());
            esModel.setSkuImg(x.getSkuDefaultImg());

            // TODO 1.  hasStock发送远程调用,查询是否有库存

            // TODO 2.  hotScore 热度评分。0,后面可以扩展

            // TODO 3.  brandName brandImg  catalogName  查询品牌名字和分类名字,以及品牌图片
            BrandEntity brandEntity = brandService.getById(esModel.getBrandId());
            esModel.setBrandName(brandEntity.getName());
            esModel.setBrandImg(brandEntity.getLogo());
            CategoryEntity categoryEntity = categoryService.getById(esModel.getCatalogId());
            esModel.setCatalogName(categoryEntity.getName());



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


        //TODO 5. 将数据发送给ES进行保存,要用search服务来做,不能直接用product服务来做。




    }

  内容待完成,今天先休息。22:52:51

 ===============

今天1月24日  22:16:25

  /**
     * 不一样的属性:skuPrice、skuImg、hasStock、hotScore、
     * brandName、brandImg、catalogName、attrs
     *
     * @param spuId
     */
    @Override
    public void up(Long spuId) {
        // 1 组装数据 查出当前spuId对应的所有sku信息
        List skus = skuInfoService.getSkusBySpuId(spuId);
        // TODO  4. 查询当前 SKU的所有 可以被用来检索的规格属性===这些规格属性是按照spu来的,所以放到外面查一遍即可
        List baseAttrs = productAttrValueService.baseAttrListForSpu(spuId);//先得到ProductAttrValueEntity

        List attrIds = baseAttrs.stream().map((x) -> x.getAttrId()).collect(Collectors.toList());//收集出所有的ID
        //然后根据attrId 在 attr表中查询,找出search_type==1的记录。也就是可以检索的记录
        List searchAttrIds = attrService.selectSearchAttrIds(attrIds);
        Set idSet = new HashSet<>(searchAttrIds);// 这个时候还只是得到了 符合条件的ID,但是我们最终要的是ProductAttrValueEntity,所以要在基础的过滤一下
        List attrsList = baseAttrs.stream() //注意这里是用Attrs 封装的,这样就可以直接放到esModel中了
                .filter((x) -> {
                    return idSet.contains(x.getAttrId());
                })
                .map((x) -> {
                    SkuEsModel.Attrs attr = new SkuEsModel.Attrs();
                    BeanUtils.copyProperties(x, attr);
                    return attr;
                }).collect(Collectors.toList());

        // TODO 1.  hasStock发送远程调用,查询是否有库存
        //=============注意这里是远程调用,可能由于网络波动这里会出现异常导致后面都不能执行
        Map stockMap = null;
        try {
            List skuIds = skus.stream().map((sku) -> sku.getSkuId()).collect(Collectors.toList());
            R hasStock = wareFeignService.getSkuHasStock(skuIds);
            List stockVos = (List) hasStock.get("data");
            // skuId 对应 是否有库存
            stockMap = stockVos.stream()
                    .collect(Collectors.toMap(
                            (x) -> x.getSkuId(),
                            (x) -> x.getHasStock()
                    ));
            log.warn("服务调用成功" + hasStock);
        } catch (Exception e) {
            log.error("库存服务调用失败: 原因{}", e);
        }


        // 2 封装每个sku的信息
        Map finalStockMap = stockMap;
        List uoProducts = skus.stream().map((x) -> {
            SkuEsModel esModel = new SkuEsModel();
            //一样的属性:
            BeanUtils.copyProperties(x, esModel);//这个是spring的类 把当前遍历的sku拷贝到esModel中

//不一样的属性:skuPrice、skuImg、hasStock、hotScore、brandName、brandImg、catalogName、attrs
            //skuPrice、skuImg
            esModel.setSkuPrice(x.getPrice());
            esModel.setSkuImg(x.getSkuDefaultImg());

            //设置库存
            if (finalStockMap == null) {
                esModel.setHasStock(true);
            } else {
                esModel.setHasStock(finalStockMap.get(x.getSkuId()));
            }

            // TODO 2.  hotScore 热度评分。0,后面可以扩展
            esModel.setHotScore(0L);

            // TODO 3.  brandName brandImg  catalogName  查询品牌名字和分类名字,以及品牌图片
            BrandEntity brandEntity = brandService.getById(esModel.getBrandId());
            esModel.setBrandName(brandEntity.getName());
            esModel.setBrandImg(brandEntity.getLogo());
            CategoryEntity categoryEntity = categoryService.getById(esModel.getCatalogId());
            esModel.setCatalogName(categoryEntity.getName());
            //设置检索属性
            esModel.setAttrs(attrsList);


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


        //TODO 5. 将数据发送给ES进行保存,要用search服务来做,不能直接用product服务来做。


  



    }

   还差一个用search服务发给 ES 的步骤。

上面远程调用ware服务:

在ware服务中加一个 controller方法

    //查询SKU是否有库存
    //@RequestBody 这个注解就是说,将请求体里面的JSON数据转换为 这个List
    @PostMapping("/hasstock")
    public R getSkuHasStock(@RequestBody List skuIds){

        //返回的话,只需返回 sku_id 和 库存量 就行了。所以封装VO
        List stockVos =  wareSkuService.getSkusStock(skuIds);
        return R.ok().put("data",stockVos);
    }

然后service遍历skuids ,对于每个skuid查询数据库看有没有库存:

    @Override
    public List getSkusStock(List skuIds) {
        return skuIds.stream()
                .map((skuId) -> {
                    SkuHasStockVo skuHasStockVo = new SkuHasStockVo();
                    //查询数据库
                    long count = baseMapper.getSkusStock(skuId);
                    skuHasStockVo.setSkuId(skuId);
                    skuHasStockVo.setHasStock(count>0);

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

    }
    //签名上只有一个参数,写什么都可以,但是多个参数就要  @Param 注解。
    long getSkusStock(Long skuId);
    

然后product服务进行远程调用

package com.atguigu.gulimall.product.feign;

import com.atguigu.common.utils.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;

@FeignClient("gulimall-ware")
public interface WareFeignService {

    /**
     * 视频中说这个返回值有问题,我感觉可以,直接取data里面的数据一样的,不知道为什么视频中提出了三种方案。。
     * 1.  R 设计的时候加上泛型
     * 2.  直接返回我们需要的结果
     * 3.  自己封装解析结果----给R类提供方法返回指定数据。
     */
    @PostMapping("/ware/waresku/hasstock")
    R getSkuHasStock(@RequestBody List SkuIds);

}

视频把这个返回设计为了R《T》 泛型的形式,后来我想了一下,可能原因就是,写ware服务的人提供返回的类型指定好,然后调用的人不用管返回的类型在强转,直接用ware服务提供的返回类型。

不知道理解的对不对。

总体看上去业务也不算复杂,不过比我之前写的东西还是复杂一些。待会写ES的那块