迁移完成商品搜索的插入
This commit is contained in:
@@ -0,0 +1 @@
|
||||
package cn.iocoder.mall.searchservice.rpc;
|
||||
@@ -0,0 +1,7 @@
|
||||
package cn.iocoder.mall.searchservice.rpc.product;
|
||||
|
||||
/**
|
||||
* 商品搜索 RPC 接口
|
||||
*/
|
||||
public interface SearchProductRpc {
|
||||
}
|
||||
@@ -32,6 +32,13 @@
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<!-- 搜索服务 -->
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>search-service-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- MQ 相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
package cn.iocoder.mall.searchservice;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SearchServiceApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 解决 ES java.lang.IllegalStateException: availableProcessors is already
|
||||
System.setProperty("es.set.netty.runtime.available.processors", "false");
|
||||
SpringApplication.run(SearchServiceApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package cn.iocoder.mall.searchservice.convert;
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.mall.searchservice.convert.product;
|
||||
|
||||
import cn.iocoder.mall.productservice.rpc.category.dto.ProductCategoryRespDTO;
|
||||
import cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuRespDTO;
|
||||
import cn.iocoder.mall.searchservice.dal.es.dataobject.ESProductDO;
|
||||
import cn.iocoder.mall.searchservice.service.product.bo.SearchProductCreateBO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface SearchProductConvert {
|
||||
|
||||
SearchProductConvert INSTANCE = Mappers.getMapper(SearchProductConvert.class);
|
||||
|
||||
|
||||
@Mapping(source = "spu.id", target = "id")
|
||||
@Mapping(source = "spu.name", target = "name")
|
||||
@Mapping(source = "spu.sellPoint", target = "sellPoint")
|
||||
@Mapping(source = "spu.description", target = "description")
|
||||
@Mapping(source = "spu.cid", target = "cid")
|
||||
@Mapping(source = "category.name", target = "categoryName")
|
||||
@Mapping(source = "spu.picUrls", target = "picUrls")
|
||||
@Mapping(source = "spu.visible", target = "visible")
|
||||
@Mapping(source = "spu.sort", target = "sort")
|
||||
SearchProductCreateBO convert(ProductSpuRespDTO spu, ProductCategoryRespDTO category);
|
||||
|
||||
ESProductDO convert(SearchProductCreateBO bean);
|
||||
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import java.util.List;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
|
||||
|
||||
@Repository
|
||||
public interface ProductRepository extends ElasticsearchRepository<ESProductDO, Integer> {
|
||||
public interface ESProductRepository extends ElasticsearchRepository<ESProductDO, Integer> {
|
||||
|
||||
@Deprecated
|
||||
ESProductDO findByName(String name);
|
||||
@@ -1,40 +0,0 @@
|
||||
package cn.iocoder.mall.searchservice.manager.product;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.productservice.rpc.category.ProductCategoryRpc;
|
||||
import cn.iocoder.mall.productservice.rpc.sku.ProductSkuRpc;
|
||||
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuListQueryReqDTO;
|
||||
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO;
|
||||
import cn.iocoder.mall.productservice.rpc.spu.ProductSpuRpc;
|
||||
import cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuRespDTO;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class ProductSearchManager {
|
||||
|
||||
@DubboReference(version = "${dubbo.consumer.ProductSpuRpc.version}")
|
||||
private ProductSpuRpc productSpuRpc;
|
||||
@DubboReference(version = "${dubbo.consumer.ProductSkuRpc.version}")
|
||||
private ProductSkuRpc productSkuRpc;
|
||||
@DubboReference(version = "${dubbo.consumer.ProductCategoryRpc.version}")
|
||||
private ProductCategoryRpc productCategoryRpc;
|
||||
|
||||
// @DubboReference( version = "${dubbo.consumer.CartService.version}")
|
||||
// private CartService cartService;
|
||||
|
||||
public Boolean saveProduct(Integer id) {
|
||||
// 获得商品 SPU
|
||||
CommonResult<ProductSpuRespDTO> productSpuResult = productSpuRpc.getProductSpu(id);
|
||||
productSpuResult.checkError();
|
||||
// 获得商品 SKU
|
||||
CommonResult<List<ProductSkuRespDTO>> listProductSkusResult =
|
||||
productSkuRpc.listProductSkus(new ProductSkuListQueryReqDTO().setProductSpuId(id));
|
||||
listProductSkusResult.checkError();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package cn.iocoder.mall.searchservice.manager.product;
|
||||
|
||||
import cn.iocoder.common.framework.util.CollectionUtils;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.productservice.rpc.category.ProductCategoryRpc;
|
||||
import cn.iocoder.mall.productservice.rpc.category.dto.ProductCategoryRespDTO;
|
||||
import cn.iocoder.mall.productservice.rpc.sku.ProductSkuRpc;
|
||||
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuListQueryReqDTO;
|
||||
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO;
|
||||
import cn.iocoder.mall.productservice.rpc.spu.ProductSpuRpc;
|
||||
import cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuRespDTO;
|
||||
import cn.iocoder.mall.searchservice.convert.product.SearchProductConvert;
|
||||
import cn.iocoder.mall.searchservice.service.product.SearchProductService;
|
||||
import cn.iocoder.mall.searchservice.service.product.bo.SearchProductCreateBO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class SearchProductManager {
|
||||
|
||||
@DubboReference(version = "${dubbo.consumer.ProductSpuRpc.version}")
|
||||
private ProductSpuRpc productSpuRpc;
|
||||
@DubboReference(version = "${dubbo.consumer.ProductSkuRpc.version}")
|
||||
private ProductSkuRpc productSkuRpc;
|
||||
@DubboReference(version = "${dubbo.consumer.ProductCategoryRpc.version}")
|
||||
private ProductCategoryRpc productCategoryRpc;
|
||||
|
||||
// @DubboReference( version = "${dubbo.consumer.CartService.version}")
|
||||
// private CartService cartService;
|
||||
|
||||
@Autowired
|
||||
private SearchProductService searchProductService;
|
||||
|
||||
public Boolean saveProduct(Integer id) {
|
||||
// 获得商品 SPU
|
||||
CommonResult<ProductSpuRespDTO> productSpuResult = productSpuRpc.getProductSpu(id);
|
||||
productSpuResult.checkError();
|
||||
if (productSpuResult.getData() == null) {
|
||||
log.error("[saveProduct][商品 SPU({}) 不存在]", id);
|
||||
return false;
|
||||
}
|
||||
// 获得商品 SKU
|
||||
CommonResult<List<ProductSkuRespDTO>> listProductSkusResult =
|
||||
productSkuRpc.listProductSkus(new ProductSkuListQueryReqDTO().setProductSpuId(id));
|
||||
listProductSkusResult.checkError();
|
||||
if (CollectionUtils.isEmpty(listProductSkusResult.getData())) {
|
||||
log.error("[saveProduct][商品 SPU({}) 的 SKU 不存在]", id);
|
||||
return false;
|
||||
}
|
||||
// 获得商品分类
|
||||
CommonResult<ProductCategoryRespDTO> getProductCategoryResult =
|
||||
productCategoryRpc.getProductCategory(productSpuResult.getData().getCid());
|
||||
getProductCategoryResult.checkError();
|
||||
if (getProductCategoryResult.getData() == null) {
|
||||
log.error("[saveProduct][商品 SPU({}) 的分类({}) 不存在]", id, productSpuResult.getData().getCid());
|
||||
return false;
|
||||
}
|
||||
// 保存商品到 ES 中
|
||||
SearchProductCreateBO searchProductCreateBO = SearchProductConvert.INSTANCE.convert(
|
||||
productSpuResult.getData(), getProductCategoryResult.getData());
|
||||
ProductSkuRespDTO productSku = listProductSkusResult.getData().stream()
|
||||
.min(Comparator.comparing(ProductSkuRespDTO::getPrice)).orElse(null);
|
||||
assert productSku != null;
|
||||
// // 价格计算 TODO 芋艿:需要补充,暂时使用这个逻辑
|
||||
// CalcSkuPriceBO calSkuPriceResult = cartService.calcSkuPrice(sku.getId());
|
||||
searchProductCreateBO.setOriginalPrice(productSku.getPrice());
|
||||
searchProductCreateBO.setBuyPrice(productSku.getPrice());
|
||||
searchProductCreateBO.setQuantity(productSku.getQuantity());
|
||||
searchProductService.createSearchProduct(searchProductCreateBO);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.iocoder.mall.searchservice.mq.consumer;
|
||||
|
||||
import cn.iocoder.mall.searchservice.manager.product.SearchProductManager;
|
||||
import cn.iocoder.mall.searchservice.mq.consumer.message.ProductUpdateMessage;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@Service
|
||||
@RocketMQMessageListener(
|
||||
topic = ProductUpdateMessage.TOPIC,
|
||||
consumerGroup = "${spring.application.name}-consumer-group-" + ProductUpdateMessage.TOPIC
|
||||
)
|
||||
public class PayTransactionPaySuccessConsumer implements RocketMQListener<ProductUpdateMessage> {
|
||||
|
||||
@Autowired
|
||||
private SearchProductManager productSearchManager;
|
||||
|
||||
@Override
|
||||
public void onMessage(ProductUpdateMessage message) {
|
||||
Boolean result = productSearchManager.saveProduct(message.getId());
|
||||
Assert.isTrue(result, String.format("重构商品(%d)的 ES 索引,必然成功。实际结果是 %s", message.getId(), result));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.iocoder.mall.searchservice.mq.consumer.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 商品更新(包括创建)消息
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class ProductUpdateMessage {
|
||||
|
||||
public static final String TOPIC = "ProductUpdate";
|
||||
|
||||
/**
|
||||
* 商品编号
|
||||
*/
|
||||
private Integer id;
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package cn.iocoder.mall.searchservice.rpc;
|
||||
@@ -0,0 +1,7 @@
|
||||
package cn.iocoder.mall.searchservice.rpc.product;
|
||||
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
|
||||
@DubboService
|
||||
public class SearchProductRpcImpl implements SearchProductRpc {
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package cn.iocoder.mall.searchservice.service.product;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class ProductSearchService {
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package cn.iocoder.mall.searchservice.service.product;
|
||||
|
||||
import cn.iocoder.mall.searchservice.convert.product.SearchProductConvert;
|
||||
import cn.iocoder.mall.searchservice.dal.es.dataobject.ESProductDO;
|
||||
import cn.iocoder.mall.searchservice.dal.es.repository.ESProductRepository;
|
||||
import cn.iocoder.mall.searchservice.service.product.bo.SearchProductCreateBO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class SearchProductService {
|
||||
|
||||
@Autowired
|
||||
private ESProductRepository productRepository;
|
||||
|
||||
public void createSearchProduct(SearchProductCreateBO createBO) {
|
||||
ESProductDO productDO = SearchProductConvert.INSTANCE.convert(createBO);
|
||||
productRepository.save(productDO);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package cn.iocoder.mall.searchservice.service.product.bo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 搜索商品创建 BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors
|
||||
public class SearchProductCreateBO {
|
||||
|
||||
private Integer id;
|
||||
|
||||
// ========== 基本信息 =========
|
||||
/**
|
||||
* SPU 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 卖点
|
||||
*/
|
||||
private String sellPoint;
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 分类编号
|
||||
*/
|
||||
private Integer cid;
|
||||
/**
|
||||
* 分类名
|
||||
*/
|
||||
private String categoryName;
|
||||
/**
|
||||
* 商品主图地数组
|
||||
*/
|
||||
private List<String> picUrls;
|
||||
|
||||
// ========== 其他信息 =========
|
||||
/**
|
||||
* 是否上架商品(是否可见)。
|
||||
*
|
||||
* true 为已上架
|
||||
* false 为已下架
|
||||
*/
|
||||
private Boolean visible;
|
||||
/**
|
||||
* 排序字段
|
||||
*/
|
||||
private Integer sort;
|
||||
|
||||
// ========== Sku 相关字段 =========
|
||||
/**
|
||||
* 原价格,单位:分
|
||||
*/
|
||||
private Integer originalPrice;
|
||||
/**
|
||||
* 购买价格,单位:分。
|
||||
*/
|
||||
private Integer buyPrice;
|
||||
/**
|
||||
* 库存数量
|
||||
*/
|
||||
private Integer quantity;
|
||||
|
||||
// ========== 促销活动相关字段 =========
|
||||
// 目前只促销单体商品促销,目前仅限制折扣。
|
||||
/**
|
||||
* 促销活动编号
|
||||
*/
|
||||
private Integer promotionActivityId;
|
||||
/**
|
||||
* 促销活动标题
|
||||
*/
|
||||
private String promotionActivityTitle;
|
||||
/**
|
||||
* 促销活动类型
|
||||
*/
|
||||
private Integer promotionActivityType;
|
||||
|
||||
}
|
||||
@@ -5,6 +5,16 @@ spring:
|
||||
# Profile 的配置项
|
||||
profiles:
|
||||
active: local
|
||||
# Elasticsearch 配置项
|
||||
data:
|
||||
elasticsearch:
|
||||
cluster-name: elasticsearch
|
||||
cluster-nodes: 400-infra.server.iocoder.cn:9300
|
||||
repositories:
|
||||
enable: true
|
||||
elasticsearch:
|
||||
rest:
|
||||
uris: 400-infra.server.iocoder.cn:9200
|
||||
|
||||
# Dubbo 配置项
|
||||
dubbo:
|
||||
@@ -17,7 +27,7 @@ dubbo:
|
||||
port: -1
|
||||
# Dubbo 提供服务的扫描基础包
|
||||
scan:
|
||||
base-packages: cn.iocoder.mall.searrchservice.rpc
|
||||
base-packages: cn.iocoder.mall.searchservice.rpc
|
||||
# Dubbo 服务提供者的配置
|
||||
provider:
|
||||
filter: -exception
|
||||
@@ -31,16 +41,16 @@ dubbo:
|
||||
version: 1.0.0
|
||||
ProductSpuRpc:
|
||||
version: 1.0.0
|
||||
ProductSkuRpc:
|
||||
version: 1.0.0
|
||||
|
||||
# RocketMQ 配置项
|
||||
rocketmq:
|
||||
name-server: 400-infra.server.iocoder.cn:9876
|
||||
producer:
|
||||
group: ${spring.application.name}-producer-group
|
||||
|
||||
# Mall 配置项
|
||||
mall:
|
||||
# 错误码配置项对应 ErrorCodeProperties 配置类
|
||||
error-code:
|
||||
group: ${spring.application.name}
|
||||
constants-class: cn.iocoder.mall.searrchservice.enums.ProductErrorCodeConstants
|
||||
constants-class: cn.iocoder.mall.searchservice.enums.ProductErrorCodeConstants
|
||||
|
||||
Reference in New Issue
Block a user