谷粒商城-商品上架

news2024/9/21 21:55:34

1.sku在es中的存储模型分析(spring整和es)

es中所有数据存在内存中,内存产品贵,能节省就节省,只保存有用的信息

两种保存方法:(空间换时间,时间换空间):

我们选空间换时间

ES中放这些东西:

 "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"
          }
        }
      }
    }
  }
}

 //nested嵌入式的数据类型,

因为数组类型不标记nested的数据处理时会被扁平化处理(如下图),所以检索时就会出现问题,当我们查询first包含Alice且last包含Smith时是会查到结果的,因为被扁平化处理,first数组里查到了Alice,而且last数组里也查到了smith,所以当数组中的每个单元是对象的时候我们就可以用nested的数据类型,这样就不会出现扁平化处理这个错误 

2.构造基本数据(商品上架功能编写)

根据接口文档,来到product的spuinfo下:

因为es里存的是我们挑出来的有用的信息而且需要product服务和search服务通信,正常开发权限问题有可能需要在product和search里都建立一个esModel的TO类,但是我们为了方便开发,可以直接在common里建这个TO:

然后来到实现类里来写方法体:(业务逻辑,我们不仅要查是否有库存,也要把可检索的规格属性一起存进es里,方便检索)

1.查出当前spuid对应的所有sku信息,再通过sku信息拿到所有的skuId组成数组,我们用这个数组去查这些sku是否都有库存(发送远程调用gulimall-ware服务),查出来的结果,用了一个map来装(Long,Boolean)这里用到了fastjson进行逆转(把R里的数据转成我们想要的对象),然后把是否有库存和skuid设置进 esModel 这个TO类里.

2.通过brandService和esModel的brandId查出品牌相关的name和img,通过catalogService和esModel的catalogId查出三级分类相关的name,放进 esModel

3.通过spuid查出所有sku的规格属性,把规格属性的id组成一个数组,遍历数组找到可检索的规格属性,通过过滤和映射把所有可检索的规格属性放进SkuEsModel类的内部类Attrs里,组成attrList的List,然后设置进esModel里

4.通过上述流程esModel里数据就充足了,我们通过远程调用gulimall-search服务,来将数据发给es保存

5.保存成功,修改当前spu的状态为 已上架

以下是部分代码:

SpuInfoServiceImpl:主方法体:
    @Override
    public void up(Long spuId) {
        //1.1查出当前spuid对应的所有sku信息,品牌的名字
        List<SkuInfoEntity> skus=skuInfoService.getSkusBySpuId(spuId);
        List<Long> skuIdList = skus.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());//拿到所有的skuId ,方便我们用id去查库存
        //TODO 4.查询当前SkU的所有可以被用来检索的规格属性
        List<ProductAttrValueEntity> baseAttrs = productAttrValueService.baseAttrListForSpu(spuId);//查出SKU的所有规格属性
        List<Long> attrIds = baseAttrs.stream().map(attr -> {
            return attr.getAttrId();
        }).collect(Collectors.toList());//把这些规格属性的ID组成一个数组

        List<Long> searchAttrIds= attrService.selectSearchAttrs(attrIds);//通过遍历这个规格属性的Id,找到 可检索 的 规格属性的Id

        Set<Long> idSet=new HashSet<>(searchAttrIds);//这里转成Set不是为了去重是因为set的查找操作时间复杂度是 O(1),而 List 的查找操作时间复杂度是 O(n)

        List<SkuEsModel.Attrs> attrsList = baseAttrs.stream().filter(item -> {//baseAttrs 里放的是规格属性的实体类,我们通过之前的查到的可检索的规格属性的ID,把实体类其中不可检索的过滤掉
            return idSet.contains(item.getAttrId());
        }).map(item -> {//再把 可检索的规格属性 映射成为SkuEsModel的内部类Attrs,方便我们底下的set
            SkuEsModel.Attrs attrs = new SkuEsModel.Attrs();
            BeanUtils.copyProperties(item, attrs);
            return attrs;
        }).collect(Collectors.toList());//这个stream流的功能是找出 baseAttrs 里的可检索的规格属性,装进 SkuEsModel的内部类Attrs(attrs) 里
        //TODO 1.发送远程调用,库存系统查询是否有库存 因为是批量所以拿出来
        Map<Long, Boolean> stockMap=null;
        try {
            R r = wareFeignService.getSkusHasStock(skuIdList);
            TypeReference<List<SkuHasStockVo>> typeReference = new TypeReference<>() {};
            stockMap = r.getData(typeReference).stream().collect(Collectors.toMap(SkuHasStockVo::getSkuId, item -> item.getHasStock()));
        }catch (Exception e){
            log.error("库存查询服务异常:原因{}",e);
        }
        //1.2封装每个sku的信息
        Map<Long, Boolean> finalStockMap = stockMap;
        List<SkuEsModel> upProducts = skus.stream().map(sku -> {
            //组装需要的数据
            SkuEsModel esModel = new SkuEsModel();
            BeanUtils.copyProperties(sku,esModel);
            esModel.setSkuPrice(sku.getPrice());
            esModel.setSkuImg(sku.getSkuDefaultImg());
            //TODO 1.发送远程调用,库存系统查询是否有库存

            //设置库存信息
            if (finalStockMap ==null){
                esModel.setHasStock(true);
            }else {
                esModel.setHasStock(finalStockMap.get(sku.getSkuId()));
            }
            //TODO 2.热度评分,默认刚上架为0后续可能有复杂的热度算法,后续再说
            esModel.setHotScore(0L);
            //TODO 3.查询品牌和分类信息
            BrandEntity brand = brandService.getById(esModel.getBrandId());
            esModel.setBrandName(brand.getName());
            esModel.setBrandImg(brand.getLogo());
            CategoryEntity category = categoryService.getById(esModel.getCatalogId());
            esModel.setCatalogName(category.getName());

            //设置检索属性
            esModel.setAttrs(attrsList);

            return esModel;
        }).collect(Collectors.toList());
        //TODO 5.将数据发给es进行保存  gulimall-search服务
        R r = searchFeignService.productStatusUp(upProducts);
        if(r.getCode()==0){
            //远程调用成功
            //TODO 6.修改当前SPU的状态
            baseMapper.updateSpuStatus(spuId, ProductConstant.StatusEnum.UP_SPU.getCode());
        }else {
            //远程调用失败
            //TODO 7.重复调用? 接口幂等性;重试机制?
            //feign的调用流程
            /**
             * 1.构造请求数据,将对象转为json
             * 2.发送请求进行执行(执行成功会解码相应的数据)
             * 3.执行请求会有重试机制
             */
        }
    }

wear查询是否有库存:

   public List<SkuHasStockVo> getSkusHasStock(List<Long> skuIds) {
        List<SkuHasStockVo> collect = skuIds.stream().map(skuId -> {
            SkuHasStockVo vo = new SkuHasStockVo();
            //查询当前sku的总库存量
            Long count= baseMapper.getSkuStock(skuId);
            vo.setSkuId(skuId);
            vo.setHasStock(count==null?false:count>0);
            return vo;
        }).collect(Collectors.toList());
        return collect;
    }

统一返回类R里新增的方法:

//利用fastjson进行逆转
	public <T> T getData(TypeReference<T> typeReference){
		Object data = get("data");
		String s = JSON.toJSONString(data);
		T t = JSON.parseObject(s, typeReference);
		return t;
	}
	public R setData(Object data){
		put("data",data);
		return this;
	}

gulimall-search的controller类:

 //上架商品
    @PostMapping("/product")
    public R  productStatusUp(@RequestBody List<SkuEsModel> skuEsModels){
        boolean b=false;
        try {
            b=productSaveService.productStatusUp(skuEsModels);
        }catch (Exception e){
            log.error("ElasticSaveController商品上架错误:{}",e);
            return R.error(BizCodeEnume.PRODUCT_UP_EXCEPTION.getCode(),BizCodeEnume.PRODUCT_UP_EXCEPTION.getMsg());
        }
        if (!b){
            return R.ok();
        }else {
            return R.error(BizCodeEnume.PRODUCT_UP_EXCEPTION.getCode(),BizCodeEnume.PRODUCT_UP_EXCEPTION.getMsg());
        }
    }

方法的实现:

    @Override
    public Boolean productStatusUp(List<SkuEsModel> skuEsModels) throws IOException {
        //保存进es
        //1.给ES中建立索引: product,建立好映射关系
        //2.给ES中保存数据:批量操作bulk
        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, GulimallElasticSearchConfig.COMMON_OPTIONS);
        //TODO 如果批量错误 可以处理错误
        Boolean b=bulk.hasFailures();
        List<String> collect = Arrays.stream(bulk.getItems()).map(item -> {
            return item.getId();
        }).collect(Collectors.toList());
        log.info("商品上架完成:{}",collect);
        return b;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1934680.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ClickHouse 入门(二)【基础SQL操作】

1、ClickHouse 1.1、SQL 操作 这里只介绍一些和我们之前 MySQL 不同的语法&#xff1b; 1.1.1、Update 和 Delete ClickHouse 提供了 Delete 和 Update 的能力&#xff0c;这类操作被称为 Mutation 查询&#xff08;可变查询&#xff09;&#xff0c;它可以看 做 Alter 的一…

国产化低功耗HDMI转VGA方案,大量出货产品,广泛应用在显示器以及广告机产品

芯片描述&#xff1a; 兼具高性能和低成本效益的优点&#xff0c;是一款可以将高清视频 HDMI1.4 数字信号转换成 VGA 模拟信号输出的芯片。不需要提供外部电源&#xff0c;ICNM7301 就可以在正常模式下使用&#xff1b;ICNM7301 广 泛适用于各种市场系统和显示应用体系&#x…

2024-07-18 Unity插件 Odin Inspector8 —— Type Specific Attributes

文章目录 1 说明2 特定类型特性2.1 AssetList2.2 AssetSelector2.3 ChildGameObjectsOnly2.4 ColorPalette2.5 DisplayAsString2.6 EnumPaging2.7 EnumToggleButtons2.8 FilePath2.9 FolderPath2.10 HideInInlineEditors2.11 HideInTables2.12 HideMonoScript2.13 HideReferenc…

【 FPGA 线下免费体验馆】高端 AMD- xilinx 16 nm UltraScale +系列

在复杂的FPGA 开发的过程中&#xff0c;需要能够满足高速、高精度、多通道等的复杂应用。而一个简单的 FPGA 开发板是不具备这些的&#xff0c;因此需要用更高端&#xff0c;大容量&#xff0c;高速IO的 FPGA 芯片与其他硬件组成一个完整的系统开发。这里就产生了高端 FPGA 开发…

拍视频麦克风什么牌子好,什么麦克风音质好,无线麦克风品牌推荐

​当我们想要记录生活中的精彩瞬间&#xff0c;或是在工作中展现专业的一面时&#xff0c;声音的质量显得尤为重要。想象一下&#xff0c;在一间教室中&#xff0c;老师使用无线领夹麦克风&#xff0c;让每一个知识点都能准确无误地传达给学生&#xff1b;在一场激烈的体育赛事…

基于springboot新生宿舍管理系统

系统背景 在当今高等教育日益普及的时代背景下&#xff0c;高校作为知识传播与创新的重要基地&#xff0c;其基础设施的智能化管理显得尤为重要。新生宿舍作为大学生活的起点&#xff0c;不仅是学生日常生活与学习的重要场所&#xff0c;也是培养学生独立生活能力和团队合作精神…

从安装Node到TypeScript到VsCode的配置教程

从安装Node到TypeScript到VsCode的配置教程 1.下载Node安装包&#xff0c; 链接 2.双击安装包&#xff0c;选择安装路径&#xff0c;如下&#xff1a; 3.一直点击下一步&#xff0c;直至安装结束即可&#xff1a; 这个时候&#xff0c;node会默认配置好环境变量&#xff0c;并且…

Kotlin泛型实化

内联函数 reified实现 1. 内联函数 内联函数中的代码会在编译的时候自动被替换到调用它的地方&#xff0c;这样的话也就不存在什么泛型擦除的问题了&#xff0c;因为代码在编译之后会直接使用实际的类型来替代内联函数中的泛型声明。 2. reified关键字 在Kotlin中&#xff0…

webrtc QOS方法十三(视频渲染平滑)

一、背景介绍 视频渲染时间的确定需要考虑三方面的因素&#xff1a;网络抖动、网络延时、音视频同步 网络抖动&#xff1a;视频帧在网络上传输&#xff0c;会受到网络抖动的影响&#xff0c;不能收到立刻播放&#xff0c;需要进行适当的平滑 网络延时&#xff1a;一些报文在…

Axure 教程 | 设置文本框背景透明

​在AXURE软件中&#xff0c;部件样式可以编辑&#xff0c;但有时却无法满足所有个性化原型的需求。例如文本框部件&#xff0c;可以设置是否隐藏边框&#xff0c;但即使隐藏边框之后&#xff0c;文本框还会有白色的背景。 当界面需要一个无背景色的输入框时&#xff0c;对于完…

h5点击电话号跳转手机拨号

需要使用到h5的 <a>标签 我们首先在<head>标签中添加代码 <meta name"format-detection" content"telephoneyes"/>然后再想要的位置添加代码 <a href"tel:10086"> 点击拨打&#xff1a;10086 </a> 这样功能就实现…

QtC++ 设计模式(五)——状态模式

状态模式 序言理解源码 序言 设计模式只是一个抽象的设计模式方法&#xff0c;并不是一个固定使用的搭配&#xff0c;就算是普通switch语句&#xff0c;Map&#xff0c;乃至状态机都是状态模式的其中一种实现方法 状态模式看起来好像和策略模式差不多&#xff0c;主要是其的侧…

FastAPI -- 第三弹(自定义响应、中间件、代理、WebSockets)

路径操作的高级配置 OpenAPI 的 operationId from fastapi import FastAPIapp FastAPI()# 通过 operation_id 参数设置 app.get("/items/", operation_id"some_specific_id_you_define") async def read_items():return [{"item_id": "F…

基于Llama Index构建RAG应用

前言 Hello&#xff0c;大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者&#xff0c;本文参与活动是2024 DataWhale AI夏令营&#xff1b;&#x1f632; 在本文中作者将通过&#xff1a; Gradio、Streamlit和LlamaIndex介绍 LlamaIndex 构…

与VR融合的LED显示屏

随着技术的飞速发展&#xff0c;广告行业已经迎来了3.0时代&#xff0c;这标志着户外LED显示屏不再仅仅局限于空间展示&#xff0c;而是转向了一个全新的维度——“空间时间人”的场景化营销。这种转变要求LED显示屏行业不仅要增强显示技术&#xff0c;还要将消费者的个性化特征…

【中项】系统集成项目管理工程师-第2章 信息技术发展-2.1信息技术及其发展-2.1.1计算机软硬件与2.1.2计算机网络

前言&#xff1a;系统集成项目管理工程师专业&#xff0c;现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试&#xff0c;全称为“全国计算机与软件专业技术资格&#xff08;水平&#xff09;考试”&…

Spring框架之DI依赖注入

Di(Dependence Injection)依赖注入,在spring框架负责创建bean对象时,动态地将依赖对象注入到其它对象中 一、什么是依赖注入。 我们在下面构建spring的过程中体会依赖注入&#xff1b; 从上面的图中我们知道&#xff0c;在ssm框架中服务层&#xff08;server&#xff09;无法直…

【操作系统】文件管理——文件共享与保护,文件系统的结构(个人笔记)

学习日期&#xff1a;2024.7.18 内容摘要&#xff1a;文件共享&#xff0c;文件保护&#xff0c;文件系统的层级结构和全局结构&#xff0c;虚拟文件系统 文件共享 操作系统提供的文件共享功能&#xff0c;可以让多个用户共享使用同一个文件。文件共享和文件复制是不一样的&a…

DP(6) | 完全背包 | Java | LeetCode 322, 179, 139 做题总结

322. 零钱兑换 我的错误答案 class Solution {public int coinChange(int[] coins, int amount) {int[][]dp new int [coins.length][amount1];for(int j0; j<amount; j) {if(coins[0] j){dp[0][coins[0]] 1;}}for(int i1; i<coins.length; i) {for(int j0; j<am…

实战篇(十一) : 拥抱交互的三维世界:利用 Processing 和 OpenGL 实现炫彩粒子系统

🌌 拥抱交互的三维世界:利用 Processing 和 OpenGL 实现炫彩粒子系统 在现代计算机图形学中,三维粒子系统是一个激动人心的领域。它不仅可以用来模拟自然现象,如烟雾、火焰和水流,还可以用来创造出令人叹为观止的视觉效果。在这篇文章中,我们将深入探讨如何使用 Proces…