分析:商品上架在es中是存sku还是spu?
代码语言:javascript复制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},
{分辨率:全高清}
]
代码语言:javascript复制缺点:如果每个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 结论:如果将规格参数单独建立索引,会出现检索时出现大量数据传输的问题,会引起网络网络
最终采用第一种
代码语言:javascript复制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" }
}
}
}
}
}
商品上架
代码语言:javascript复制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;
}
}
库存量查询
代码语言:javascript复制@PostMapping("/hasStock")
public R getSkuHasStock(@RequestBody List<Long> SkuIds){
List<SkuHasStockVo> vos = wareSkuService.getSkuHasStock(SkuIds);
return R.ok().setData(vos);
}
然后用feign调用
代码语言:javascript复制@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信息(未保存版本)
代码语言:javascript复制 @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