!188 优化初始化商品索引,增加编辑商品时,保留原商品的销量、好评率和评价量
Merge pull request !188 from OceansDeep/feature/pg
This commit is contained in:
commit
712941038b
@ -0,0 +1,30 @@
|
|||||||
|
package cn.lili.init;
|
||||||
|
|
||||||
|
import cn.lili.modules.search.service.EsGoodsIndexService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.ApplicationArguments;
|
||||||
|
import org.springframework.boot.ApplicationRunner;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author paulG
|
||||||
|
* @since 2022/6/9
|
||||||
|
**/
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class EsGoodsIndexInitRunner implements ApplicationRunner {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EsGoodsIndexService esGoodsIndexService;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(ApplicationArguments args) {
|
||||||
|
try {
|
||||||
|
esGoodsIndexService.initIndex();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("检测ES商品索引失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -115,7 +115,6 @@ public class RedisConfig extends CachingConfigurerSupport {
|
|||||||
@Bean(destroyMethod = "shutdown")
|
@Bean(destroyMethod = "shutdown")
|
||||||
public RedissonClient redisson() {
|
public RedissonClient redisson() {
|
||||||
Config config = new Config();
|
Config config = new Config();
|
||||||
|
|
||||||
if (redisProperties.getSentinel() != null && !redisProperties.getSentinel().getNodes().isEmpty()) {
|
if (redisProperties.getSentinel() != null && !redisProperties.getSentinel().getNodes().isEmpty()) {
|
||||||
// 哨兵模式
|
// 哨兵模式
|
||||||
SentinelServersConfig sentinelServersConfig = config.useSentinelServers();
|
SentinelServersConfig sentinelServersConfig = config.useSentinelServers();
|
||||||
@ -145,6 +144,7 @@ public class RedisConfig extends CachingConfigurerSupport {
|
|||||||
if (CharSequenceUtil.isNotEmpty(redisProperties.getPassword())) {
|
if (CharSequenceUtil.isNotEmpty(redisProperties.getPassword())) {
|
||||||
singleServerConfig.setPassword(redisProperties.getPassword());
|
singleServerConfig.setPassword(redisProperties.getPassword());
|
||||||
}
|
}
|
||||||
|
singleServerConfig.setPingConnectionInterval(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redisson.create(config);
|
return Redisson.create(config);
|
||||||
|
@ -123,7 +123,7 @@ public abstract class BaseElasticsearchService {
|
|||||||
" \"type\": \"keyword\"\n" +
|
" \"type\": \"keyword\"\n" +
|
||||||
" },\n" +
|
" },\n" +
|
||||||
" \"type\": {\n" +
|
" \"type\": {\n" +
|
||||||
" \"type\": \"long\"\n" +
|
" \"type\": \"integer\"\n" +
|
||||||
" },\n" +
|
" },\n" +
|
||||||
" \"value\": {\n" +
|
" \"value\": {\n" +
|
||||||
" \"type\": \"keyword\"\n" +
|
" \"type\": \"keyword\"\n" +
|
||||||
|
@ -14,6 +14,7 @@ import cn.lili.common.properties.RocketmqCustomProperties;
|
|||||||
import cn.lili.common.security.context.UserContext;
|
import cn.lili.common.security.context.UserContext;
|
||||||
import cn.lili.common.utils.SnowFlake;
|
import cn.lili.common.utils.SnowFlake;
|
||||||
import cn.lili.modules.goods.entity.dos.Goods;
|
import cn.lili.modules.goods.entity.dos.Goods;
|
||||||
|
import cn.lili.modules.goods.entity.dos.GoodsGallery;
|
||||||
import cn.lili.modules.goods.entity.dos.GoodsSku;
|
import cn.lili.modules.goods.entity.dos.GoodsSku;
|
||||||
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
|
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
|
||||||
import cn.lili.modules.goods.entity.dto.GoodsSearchParams;
|
import cn.lili.modules.goods.entity.dto.GoodsSearchParams;
|
||||||
@ -166,8 +167,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
|||||||
} else {
|
} else {
|
||||||
skuList = new ArrayList<>();
|
skuList = new ArrayList<>();
|
||||||
for (Map<String, Object> map : goodsOperationDTO.getSkuList()) {
|
for (Map<String, Object> map : goodsOperationDTO.getSkuList()) {
|
||||||
GoodsSku sku = null;
|
GoodsSku sku = GoodsSkuBuilder.build(goods, map, goodsOperationDTO);
|
||||||
sku = GoodsSkuBuilder.build(goods, map, goodsOperationDTO);
|
|
||||||
renderGoodsSku(sku, goodsOperationDTO);
|
renderGoodsSku(sku, goodsOperationDTO);
|
||||||
skuList.add(sku);
|
skuList.add(sku);
|
||||||
//如果商品状态值不对,则es索引移除
|
//如果商品状态值不对,则es索引移除
|
||||||
@ -636,6 +636,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
|||||||
// 商品销售模式渲染器
|
// 商品销售模式渲染器
|
||||||
salesModelRenders.stream().filter(i -> i.getSalesMode().equals(goodsOperationDTO.getSalesModel())).findFirst().ifPresent(i -> i.renderBatch(goodsSkuList, goodsOperationDTO));
|
salesModelRenders.stream().filter(i -> i.getSalesMode().equals(goodsOperationDTO.getSalesModel())).findFirst().ifPresent(i -> i.renderBatch(goodsSkuList, goodsOperationDTO));
|
||||||
for (GoodsSku goodsSku : goodsSkuList) {
|
for (GoodsSku goodsSku : goodsSkuList) {
|
||||||
|
extendOldSkuValue(goodsSku);
|
||||||
this.renderImages(goodsSku);
|
this.renderImages(goodsSku);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -647,22 +648,43 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
|
|||||||
* @param goodsOperationDTO 商品操作DTO
|
* @param goodsOperationDTO 商品操作DTO
|
||||||
*/
|
*/
|
||||||
void renderGoodsSku(GoodsSku goodsSku, GoodsOperationDTO goodsOperationDTO) {
|
void renderGoodsSku(GoodsSku goodsSku, GoodsOperationDTO goodsOperationDTO) {
|
||||||
|
extendOldSkuValue(goodsSku);
|
||||||
// 商品销售模式渲染器
|
// 商品销售模式渲染器
|
||||||
salesModelRenders.stream().filter(i -> i.getSalesMode().equals(goodsOperationDTO.getSalesModel())).findFirst().ifPresent(i -> i.renderSingle(goodsSku, goodsOperationDTO));
|
salesModelRenders.stream().filter(i -> i.getSalesMode().equals(goodsOperationDTO.getSalesModel())).findFirst().ifPresent(i -> i.renderSingle(goodsSku, goodsOperationDTO));
|
||||||
this.renderImages(goodsSku);
|
this.renderImages(goodsSku);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将原sku的一些不会直接传递的值放到新的sku中
|
||||||
|
*
|
||||||
|
* @param goodsSku 商品sku
|
||||||
|
*/
|
||||||
|
private void extendOldSkuValue(GoodsSku goodsSku) {
|
||||||
|
if (CharSequenceUtil.isNotEmpty(goodsSku.getGoodsId())) {
|
||||||
|
GoodsSku oldSku = this.getGoodsSkuByIdFromCache(goodsSku.getId());
|
||||||
|
if (oldSku != null) {
|
||||||
|
goodsSku.setCommentNum(oldSku.getCommentNum());
|
||||||
|
goodsSku.setViewCount(oldSku.getViewCount());
|
||||||
|
goodsSku.setBuyCount(oldSku.getBuyCount());
|
||||||
|
goodsSku.setGrade(oldSku.getGrade());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渲染sku图片
|
* 渲染sku图片
|
||||||
*
|
*
|
||||||
* @param goodsSku
|
* @param goodsSku sku
|
||||||
*/
|
*/
|
||||||
void renderImages(GoodsSku goodsSku) {
|
void renderImages(GoodsSku goodsSku) {
|
||||||
JSONObject jsonObject = JSONUtil.parseObj(goodsSku.getSpecs());
|
JSONObject jsonObject = JSONUtil.parseObj(goodsSku.getSpecs());
|
||||||
List<Map<String, String>> images = jsonObject.get("images", List.class);
|
List<Map<String, String>> images = jsonObject.get("images", List.class);
|
||||||
if (images != null && !images.isEmpty()) {
|
if (images != null && !images.isEmpty()) {
|
||||||
goodsSku.setThumbnail(goodsGalleryService.getGoodsGallery(images.get(0).get("url")).getThumbnail());
|
GoodsGallery goodsGallery = goodsGalleryService.getGoodsGallery(images.get(0).get("url"));
|
||||||
goodsSku.setSmall(goodsGalleryService.getGoodsGallery(images.get(0).get("url")).getSmall());
|
goodsSku.setBig(goodsGallery.getOriginal());
|
||||||
|
goodsSku.setOriginal(goodsGallery.getOriginal());
|
||||||
|
goodsSku.setThumbnail(goodsGallery.getThumbnail());
|
||||||
|
goodsSku.setSmall(goodsGallery.getSmall());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ import java.util.Map;
|
|||||||
* @author paulG
|
* @author paulG
|
||||||
**/
|
**/
|
||||||
@Data
|
@Data
|
||||||
@Document(indexName = "#{@elasticsearchProperties.indexPrefix}_" + EsSuffix.GOODS_INDEX_NAME)
|
@Document(indexName = "#{@elasticsearchProperties.indexPrefix}_" + EsSuffix.GOODS_INDEX_NAME, createIndex = false)
|
||||||
@ToString
|
@ToString
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
@ -215,6 +215,7 @@ public class EsGoodsIndex implements Serializable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 销售模式
|
* 销售模式
|
||||||
|
*
|
||||||
* @see cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum
|
* @see cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum
|
||||||
*/
|
*/
|
||||||
@Field(type = FieldType.Text)
|
@Field(type = FieldType.Text)
|
||||||
@ -277,7 +278,7 @@ public class EsGoodsIndex implements Serializable {
|
|||||||
* @see PromotionTypeEnum
|
* @see PromotionTypeEnum
|
||||||
* value 为 促销活动实体信息
|
* value 为 促销活动实体信息
|
||||||
*/
|
*/
|
||||||
@Field(type = FieldType.Nested)
|
@Field(type = FieldType.Text)
|
||||||
@ApiModelProperty("商品促销活动集合JSON,key 为 促销活动类型,value 为 促销活动实体信息 ")
|
@ApiModelProperty("商品促销活动集合JSON,key 为 促销活动类型,value 为 促销活动实体信息 ")
|
||||||
private String promotionMapJson;
|
private String promotionMapJson;
|
||||||
|
|
||||||
@ -316,7 +317,7 @@ public class EsGoodsIndex implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* 参数索引增加
|
* 参数索引增加
|
||||||
*
|
*
|
||||||
* @param sku 商品sku信息
|
* @param sku 商品sku信息
|
||||||
* @param goodsParamDTOS 商品参数信息
|
* @param goodsParamDTOS 商品参数信息
|
||||||
*/
|
*/
|
||||||
public EsGoodsIndex(GoodsSku sku, List<GoodsParamsDTO> goodsParamDTOS) {
|
public EsGoodsIndex(GoodsSku sku, List<GoodsParamsDTO> goodsParamDTOS) {
|
||||||
|
@ -20,7 +20,7 @@ import java.util.Map;
|
|||||||
public interface EsGoodsIndexService {
|
public interface EsGoodsIndexService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 全局索引初始化
|
* 全局索引数据初始化
|
||||||
*/
|
*/
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
@ -31,6 +31,12 @@ public interface EsGoodsIndexService {
|
|||||||
*/
|
*/
|
||||||
Map<String, Integer> getProgress();
|
Map<String, Integer> getProgress();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局索引初始化
|
||||||
|
*/
|
||||||
|
void initIndex();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加商品索引
|
* 添加商品索引
|
||||||
*
|
*
|
||||||
|
@ -66,6 +66,7 @@ import org.springframework.stereotype.Service;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -127,7 +128,7 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements
|
|||||||
Boolean flag = (Boolean) cache.get(CachePrefix.INIT_INDEX_FLAG.getPrefix());
|
Boolean flag = (Boolean) cache.get(CachePrefix.INIT_INDEX_FLAG.getPrefix());
|
||||||
//为空则默认写入没有任务
|
//为空则默认写入没有任务
|
||||||
if (flag == null) {
|
if (flag == null) {
|
||||||
cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), false);
|
cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), false, 10L, TimeUnit.MINUTES);
|
||||||
}
|
}
|
||||||
//有正在初始化的任务,则提示异常
|
//有正在初始化的任务,则提示异常
|
||||||
if (Boolean.TRUE.equals(flag)) {
|
if (Boolean.TRUE.equals(flag)) {
|
||||||
@ -200,6 +201,25 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initIndex() {
|
||||||
|
//索引名称拼接
|
||||||
|
String indexName = this.getIndexName();
|
||||||
|
|
||||||
|
//索引初始化,因为mapping结构问题:
|
||||||
|
//但是如果索引已经自动生成过,这里就不会创建索引,设置mapping,所以这里决定在初始化索引的同时,将已有索引删除,重新创建
|
||||||
|
|
||||||
|
boolean indexExist = this.indexExist(indexName);
|
||||||
|
log.info("检测 {} 索引结构是否存在:{}", indexName, indexExist);
|
||||||
|
if (!indexExist) {
|
||||||
|
|
||||||
|
log.info("初始化索引结构 {}", indexName);
|
||||||
|
//如果索引不存在,则创建索引
|
||||||
|
createIndexRequest(indexName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addIndex(EsGoodsIndex goods) {
|
public void addIndex(EsGoodsIndex goods) {
|
||||||
try {
|
try {
|
||||||
|
@ -11,10 +11,8 @@ import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
|
|||||||
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
|
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
|
||||||
import cn.lili.modules.search.entity.dos.EsGoodsRelatedInfo;
|
import cn.lili.modules.search.entity.dos.EsGoodsRelatedInfo;
|
||||||
import cn.lili.modules.search.entity.dto.EsGoodsSearchDTO;
|
import cn.lili.modules.search.entity.dto.EsGoodsSearchDTO;
|
||||||
import cn.lili.modules.search.entity.dto.HotWordsDTO;
|
|
||||||
import cn.lili.modules.search.entity.dto.ParamOptions;
|
import cn.lili.modules.search.entity.dto.ParamOptions;
|
||||||
import cn.lili.modules.search.entity.dto.SelectorOptions;
|
import cn.lili.modules.search.entity.dto.SelectorOptions;
|
||||||
import cn.lili.modules.search.service.EsGoodsIndexService;
|
|
||||||
import cn.lili.modules.search.service.EsGoodsSearchService;
|
import cn.lili.modules.search.service.EsGoodsSearchService;
|
||||||
import com.alibaba.druid.util.StringUtils;
|
import com.alibaba.druid.util.StringUtils;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -44,7 +42,6 @@ import org.springframework.data.elasticsearch.core.SearchHits;
|
|||||||
import org.springframework.data.elasticsearch.core.SearchPage;
|
import org.springframework.data.elasticsearch.core.SearchPage;
|
||||||
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
|
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
|
||||||
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
|
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
|
||||||
import org.springframework.data.redis.core.ZSetOperations;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -73,9 +70,6 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
|||||||
*/
|
*/
|
||||||
@Autowired
|
@Autowired
|
||||||
private ElasticsearchOperations restTemplate;
|
private ElasticsearchOperations restTemplate;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private EsGoodsIndexService esGoodsIndexService;
|
|
||||||
/**
|
/**
|
||||||
* 缓存
|
* 缓存
|
||||||
*/
|
*/
|
||||||
@ -84,10 +78,6 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SearchPage<EsGoodsIndex> searchGoods(EsGoodsSearchDTO searchDTO, PageVO pageVo) {
|
public SearchPage<EsGoodsIndex> searchGoods(EsGoodsSearchDTO searchDTO, PageVO pageVo) {
|
||||||
boolean exists = restTemplate.indexOps(EsGoodsIndex.class).exists();
|
|
||||||
if (!exists) {
|
|
||||||
esGoodsIndexService.init();
|
|
||||||
}
|
|
||||||
if (CharSequenceUtil.isNotBlank(searchDTO.getKeyword())) {
|
if (CharSequenceUtil.isNotBlank(searchDTO.getKeyword())) {
|
||||||
cache.incrementScore(CachePrefix.HOT_WORD.getPrefix(), searchDTO.getKeyword());
|
cache.incrementScore(CachePrefix.HOT_WORD.getPrefix(), searchDTO.getKeyword());
|
||||||
}
|
}
|
||||||
@ -364,7 +354,7 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
|||||||
this.commonSearch(filterBuilder, searchDTO);
|
this.commonSearch(filterBuilder, searchDTO);
|
||||||
|
|
||||||
//智能推荐
|
//智能推荐
|
||||||
this.recommended(filterBuilder,searchDTO);
|
this.recommended(filterBuilder, searchDTO);
|
||||||
|
|
||||||
//未上架的商品不显示
|
//未上架的商品不显示
|
||||||
filterBuilder.must(QueryBuilders.matchQuery("marketEnable", GoodsStatusEnum.UPPER.name()));
|
filterBuilder.must(QueryBuilders.matchQuery("marketEnable", GoodsStatusEnum.UPPER.name()));
|
||||||
@ -406,30 +396,31 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品推荐
|
* 商品推荐
|
||||||
|
*
|
||||||
* @param filterBuilder
|
* @param filterBuilder
|
||||||
* @param searchDTO
|
* @param searchDTO
|
||||||
*/
|
*/
|
||||||
private void recommended(BoolQueryBuilder filterBuilder, EsGoodsSearchDTO searchDTO) {
|
private void recommended(BoolQueryBuilder filterBuilder, EsGoodsSearchDTO searchDTO) {
|
||||||
|
|
||||||
String currentGoodsId = searchDTO.getCurrentGoodsId();
|
String currentGoodsId = searchDTO.getCurrentGoodsId();
|
||||||
if(CharSequenceUtil.isEmpty(currentGoodsId)) {
|
if (CharSequenceUtil.isEmpty(currentGoodsId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//排除当前商品
|
//排除当前商品
|
||||||
filterBuilder.mustNot(QueryBuilders.matchQuery("id",currentGoodsId));
|
filterBuilder.mustNot(QueryBuilders.matchQuery("id", currentGoodsId));
|
||||||
|
|
||||||
//查询当前浏览商品的索引信息
|
//查询当前浏览商品的索引信息
|
||||||
EsGoodsIndex esGoodsIndex = restTemplate.get(currentGoodsId, EsGoodsIndex.class);
|
EsGoodsIndex esGoodsIndex = restTemplate.get(currentGoodsId, EsGoodsIndex.class);
|
||||||
if(esGoodsIndex==null) {
|
if (esGoodsIndex == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//推荐与当前浏览商品相同一个二级分类下的商品
|
//推荐与当前浏览商品相同一个二级分类下的商品
|
||||||
String categoryPath = esGoodsIndex.getCategoryPath();
|
String categoryPath = esGoodsIndex.getCategoryPath();
|
||||||
if(CharSequenceUtil.isNotEmpty(categoryPath)){
|
if (CharSequenceUtil.isNotEmpty(categoryPath)) {
|
||||||
//匹配二级分类
|
//匹配二级分类
|
||||||
String substring = categoryPath.substring(0, categoryPath.lastIndexOf(","));
|
String substring = categoryPath.substring(0, categoryPath.lastIndexOf(","));
|
||||||
filterBuilder.must(QueryBuilders.wildcardQuery("categoryPath",substring+"*"));
|
filterBuilder.must(QueryBuilders.wildcardQuery("categoryPath", substring + "*"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user