【业务功能篇84】微服务SpringCloud-ElasticSearch-Kibanan-电商实例应用

一、商品上架功能

ElasticSearch实现商城系统中全文检索的流程。

1.商品ES模型

商品的映射关系

json 复制代码
PUT product 
{
	"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"
					}
				}
			}
		}
	}
}

2.netsted数据类型

如上的例子,netsted类型,避免了我们properties属性里的三个字段值同类型,他们的内容不会错乱匹配

参考官网地址:https://www.elastic.co/guide/en/elasticsearch/reference/7.4/nested.html

3.实现上架功能

3.1 创建ESModel

点击上架功能传递spuId到后台,我们需要根据SpuID查询对应的信息,然后封装到自定义的Model对象中,然后将该对象传递给mall-search服务,所以我们需要先定义这样一个Model对象

java 复制代码
@Data
public class SkuESModel {
    private Long skuId;
    private Long spuId;
    private String subTitle;
    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.2 上架逻辑实现

controller层

java 复制代码
/**
 * spu信息
 *
 */
@RestController
@RequestMapping("product/spuinfo")
public class SpuInfoController {
    @Autowired
    private SpuInfoService spuInfoService;

    /**
     * app/product/spuinfo/6/up
     * 商品的上架功能
     * 传递过来一个spuID
     * 我们就需要根据SPUID查询出需要存储在ElasticSearch中的数据
     * 然后把数据存储到ELasticSearch中,并修改该SPU的状态为上架
     */
    @PostMapping("/{spuId}/up")
    public R spuUp(@PathVariable("spuId") Long spuId){
        spuInfoService.up(spuId);
        return R.ok();
    }
}

核心service层方法实现

调用了一些同moudle下的其他实现类方法忽略

java 复制代码
/**
     * 实现商品上架--》商品相关数据存储到ElasticSearch中
     * 1.根据SpuID查询出相关的信息
     *   封装到对应的对象中
     * 2.将封装的数据存储到ElasticSearch中--》调用mall-search的远程接口
     * 3.更新SpuID对应的状态--》上架
     *
     * @param spuId
     */
    @Override
    public void up(Long spuId) {
        // 1.根据spuId查询相关的信息 封装到SkuESModel对象中
        List<SkuESModel> skuEs = new ArrayList<>();
        // 根据spuID找到对应的SKU信息
        List<SkuInfoEntity> skus = skuInfoService.getSkusBySpuId(spuId);

        // 对应的规格参数  根据spuId来查询规格参数信息
        List<SkuESModel.Attrs> attrsModel = getAttrsModel(spuId);
        // 需要根据所有的skuId获取对应的库存信息---》远程调用
        List<Long> skuIds = skus.stream().map(sku -> {
            return sku.getSkuId();
        }).collect(Collectors.toList());
        Map<Long, Boolean> skusHasStockMap = getSkusHasStock(skuIds);
        // 2.远程调用mall-search的服务,将SukESModel中的数据存储到ES中
        List<SkuESModel> skuESModels = skus.stream().map(item -> {
            SkuESModel model = new SkuESModel();
            // 先实现属性的复制
            BeanUtils.copyProperties(item,model);
            model.setSubTitle(item.getSkuTitle());
            model.setSkuPrice(item.getPrice());

            // hasStock 是否有库存 --》 库存系统查询  一次远程调用获取所有的skuId对应的库存信息
            if(skusHasStockMap == null){
                model.setHasStock(true);
            }else{
                model.setHasStock(skusHasStockMap.get(item.getSkuId()));
            }
            // hotScore 热度分 --> 默认给0即可
            model.setHotScore(0l);
            // 品牌和类型的名称
            BrandEntity brand = brandService.getById(item.getBrandId());
            CategoryEntity category = categoryService.getById(item.getCatalogId());
            model.setBrandName(brand.getName());
            model.setBrandImg(brand.getLogo());
            model.setCatalogName(category.getName());
            // 需要存储的规格数据
            model.setAttrs(attrsModel);

            return model;
        }).collect(Collectors.toList());
        // 将SkuESModel中的数据存储到ES中
        R r = searchFeginService.productStatusUp(skuESModels);
        // 3.更新SPUID对应的状态
        // 根据对应的状态更新商品的状态
        log.info("----->ES操作完成:{}" ,r.getCode());
        System.out.println("-------------->"+r.getCode());
        if(r.getCode() == 0){
            // 远程调用成功  更新商品的状态为 上架
            baseMapper.updateSpuStatusUp(spuId, ProductConstant.StatusEnum.SPU_UP.getCode());
        }else{
            // 远程调用失败
        }
    }

Feign远程调用了其他微服务module

在当前需要调用远程微服务的模块中创建接口,通过注解@FeignClient("mall-search")找到对应被调用的微服务,接着将被调用微服务的controller层的所需方法名,形参路径等都全部复制过来,就能完成远程调用

java 复制代码
@FeignClient("mall-search")
public interface SearchFeginService {

    @PostMapping("/search/save/product")
    public R productStatusUp(@RequestBody List<SkuESModel> skuESModels);
}

被调用的微服务模块Controller层

java 复制代码
/**
 *
 * 存储商城数据到ElasticSearch的服务
 */
@Slf4j
@RequestMapping("/search/save")
@RestController
public class ElasticSearchSaveController {

    @Autowired
    private ElasticSearchSaveService service;

    /**
     * 存储商品上架信息到ElasticSearch服务的接口
     * @return
     */
    @PostMapping("/product")
    public R productStatusUp(@RequestBody List<SkuESModel> skuESModels){
        Boolean b = false;
        try {
            b = service.productStatusUp(skuESModels);
        } catch (IOException e) {
           // e.printStackTrace();
            log.error("ElasticSearch商品上架错误:{}",e);
            return R.error(BizCodeEnume.PRODUCT_UP_EXCEPTION.getCode(), BizCodeEnume.PRODUCT_UP_EXCEPTION.getMsg());
        }
        if(b){
            return R.ok();
        }
        return R.error(BizCodeEnume.PRODUCT_UP_EXCEPTION.getCode(), BizCodeEnume.PRODUCT_UP_EXCEPTION.getMsg());
    }
    
相关推荐
for_ever_love__17 小时前
MySQL 高频面试题 30 问:索引、事务、锁、日志、主从与分库分表(MySQL 8.0 版)
java·数据库·spring boot·mysql·spring cloud·面试·总结
天空鸟_时光不老1 天前
13-亮点提炼:把技术说辞翻译成业务价值
java·spring boot·spring·spring cloud·mybatis
Joy T1 天前
从 Nginx 到 Gateway 再到微服务:一次 AI 请求的完整链路
nginx·微服务·gateway·controller·路由转发·ai service·接口错误排查
ofoxcoding1 天前
借助 CLAUDE.md 约束 Sonnet 5.5 多文件重构行为的提示词实践
大数据·elasticsearch·ai·重构
Elasticsearch1 天前
隆重推出 AlertZero:让你的告警队列实现 “收件箱清零” 式管理
elasticsearch
ly76891 天前
从 TF-IDF 到 BM25:Elasticsearch 相关性评分的字段长度归一化与 boost 调参边界
java·elasticsearch·query dsl·bm25·相关性评分
Thomas.Sir1 天前
第19课:Gateway过滤器、全局拦截、请求响应统一处理
spring cloud·gateway
SL-staff1 天前
技术实践:将Excel自动升级为可搜索的知识节点(JVS平台实现)
mongodb·elasticsearch·知识图谱·jvs平台·语义解析·企业文档管理·excel结构化
Elasticsearch1 天前
2026 年唯一获得端点预防与响应(EPR)满分的厂商是 Elastic
elasticsearch
vx_Biye_Design1 天前
springboot旅游管理系统18006-计算机课程设计、毕业设计
java·spring boot·后端·python·elasticsearch·django·课程设计