分析:商品上架在es中是存sku还是spu?
1)、检索的时候输入名字,是需要按照sku的title进行全文检索的
2)、检素使用商品规格,规格是spu的公共属性,每个spu是一样的
3)、按照分类id进去的都是直接列出spu的,还可以切换。
4〕、我们如果将sku的全量信息保存到es中(包括spu属性〕就太多字段了
{ skuId:1 spuId:11 skyTitile:华为mate price:999 saleCount:99 attr:[ {尺寸:5}, {CPU:高通945}, {分辨率:全高清} ]
缺点:如果每个sku都存储规格参数(如尺寸),会有冗余存储,因为每个spu对应的sku的规格参数都一样
sku索引 { spuId:1 skuId:11 } attr索引 { skuId:11 attr:[ {尺寸:5}, {CPU:高通945}, {分辨率:全高清} ] }
先找到4000个符合要求的spu,再根据4000个spu查询对应的属性,封装了4000个id,long 8B*4000=32000B=32KB 1K个人检索,就是32MB 结论:如果将规格参数单独建立索引,会出现检索时出现大量数据传输的问题,会引起网络网络
最终采用第一种
PUT product { "mappings":{ "properties": { "skuId":{ "type": "long" }, "spuId":{ "type": "keyword" }, # 不可分词 "skuTitle": { "type": "text", "analyzer": "ik_smart" # 中文分词器 }, "skuPrice": { "type": "keyword" }, # 保证精度问题 "skuImg" : { "type": "keyword" }, # 视频中有false "saleCount":{ "type":"long" }, "hasStock": { "type": "boolean" }, "hotScore": { "type": "long" }, "brandId": { "type": "long" }, "catalogId": { "type": "long" }, "brandName": {"type": "keyword"}, # 视频中有false "brandImg":{ "type": "keyword", "index": false, # 不可被检索,不生成index,只用做页面使用 "doc_values": false # 不可被聚合,默认为true }, "catalogName": {"type": "keyword" }, # 视频里有false "attrs": { "type": "nested", "properties": { "attrId": {"type": "long" }, "attrName": { "type": "keyword", "index": false, "doc_values": false }, "attrValue": {"type": "keyword" } } } } } }
商品上架
POST /product/spuinfo/{spuId}/up
@GetMapping("/skuId/{id}") public R getSkuInfoBySkuId(@PathVariable("id") Long skuId){ SpuInfoEntity entity = spuInfoService.getSpuInfoBySkuId(skuId); return R.ok().setData(entity); }
上架实体类
由于SpuInfoEntity
与索引的数据模型并不对应,所以我们要建立专门的vo进行数据传输
package com.atguigu.common.to.es; import lombok.Data; import java.math.BigDecimal; import java.util.List; @Data 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 bandId; 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; } }
库存量查询
@PostMapping("/hasStock") public R getSkuHasStock(@RequestBody List<Long> SkuIds){ List<SkuHasStockVo> vos = wareSkuService.getSkuHasStock(SkuIds); return R.ok().setData(vos); }
然后用feign调用
@FeignClient("gulimall-ware") public interface WareFeignService { /** * 1.R设计的时候可以加上泛型(用这个) * 2.直接返回我们想要的类型 * 3.自己封装解析结果 * @param skuIds * @return */ @PostMapping("/hasstock") public R<List<SkuHasStockVo>> getSkuHashStock(@RequestBody List<Long> skuIds); }
封装Es信息(未保存版本)
@Override public void up(Long spuId) { List<SkuEsModel> upProducts=new ArrayList<>(); //1.组装我们需要的数据 SkuEsModel esModel = new SkuEsModel(); //1.查出spuid对应的sku的信息,品牌信息 List<SkuInfoEntity> skus= skuInfoService.getSkusByspuId(spuId); List<Long> skuIdList = skus.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList()); //2.封装sku的信息 List<SkuEsModel> collect = skus.stream().map(sku -> { SkuEsModel esModel1 = new SkuEsModel(); BeanUtils.copyProperties(sku,esModel1); //skuPrice skuImg hasStock hoteScore esModel1.setSkuPrice(sku.getPrice()); esModel1.setSkuImg(sku.getSkuDefaultImg()); //todo 运程发送请求,库存系统查询是否有库存 Map<Long,Boolean> stockMap=null; try { R<List<SkuHasStockVo>> skuHashStock = wareFeignService.getSkuHashStock(skuIdList); stockMap = skuHashStock.getData().stream(). collect(Collectors.toMap(SkuHasStockVo::getSkuId, item -> item.getHasStock())); }catch (Exception e){ log.error("库存服务查询异常:原因{}",e); } //设置库存信息 if (stockMap==null){ esModel1.setHasStock(true); }else { esModel1.setHasStock(stockMap.get(sku.getSkuId())); } //todo 热度评分 0 esModel1.setHotScore(0L); //todo 查询品牌和分类的名字信息 BrandEntity brandEntity = brandService.getById(esModel1.getBandId()); esModel1.setBrandName(brandEntity.getName()); esModel1.setBrandImg(brandEntity.getLogo()); CategoryEntity categoryEntity = categoryService.getById(esModel1.getCatalogId()); esModel1.setCatalogName(categoryEntity.getName()); // todo 查询当前所有的sku的所有可以被检索规格属性 List<ProductAttrValueEntity> baseAttrs = attrValueService.baseAttrlistforspu(spuId); List<Long> attrIds = baseAttrs.stream().map(attr -> { return attr.getAttrId(); }).collect(Collectors.toList()); List<Long> searchAttrIds= attrService.selectSearchAttrIds(attrIds); Set<Long> idSet=new HashSet<>(searchAttrIds); List<SkuEsModel.Attrs> atts=new ArrayList<>(); List<SkuEsModel.Attrs> attrsList = baseAttrs.stream().filter(item -> { return idSet.contains(item.getAttrId()); }).map(item -> { SkuEsModel.Attrs attrs1 = new SkuEsModel.Attrs(); BeanUtils.copyProperties(item, attrs1); return attrs1; }).collect(Collectors.toList()); //设置检索属性 esModel1.setAttrs(attrsList); /** * private String bandName; * * private String brandImg; * * private String catalogName; * Attrs * @Data * static class Attrs{ * private Long attrId; * * private String attrName; * * private String attrValue; * } */ return esModel1; }).collect(Collectors.toList()); //todo 5.将数据发送给es进行保存 gulimall-search