master:针对档口上架下架,调整查询ES的数据;

pull/1121/head
liujiang 2025-11-24 16:05:52 +08:00
parent 336232541a
commit 4d58960697
9 changed files with 101 additions and 14 deletions

View File

@ -27,7 +27,7 @@ public class ElasticSearchController extends XktBaseController {
final IElasticSearchService esService;
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@PreAuthorize("@ss.hasAnyRoles('admin')")
@Log(title = "ES批量新增数据", businessType = BusinessType.INSERT)
@PutMapping("/batch-create")
public R<Integer> batchCreate(@RequestParam(required = false) Long storeId) {
@ -35,7 +35,7 @@ public class ElasticSearchController extends XktBaseController {
return R.ok();
}
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@PreAuthorize("@ss.hasAnyRoles('admin')")
@Log(title = "ES批量新增数据特定商品", businessType = BusinessType.INSERT)
@PutMapping("/prod/batch-create")
public R<Integer> batchCreateProd(@Validated @RequestBody EsProdBatchCreateVO createVO) {
@ -43,7 +43,7 @@ public class ElasticSearchController extends XktBaseController {
return R.ok();
}
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@PreAuthorize("@ss.hasAnyRoles('admin')")
@Log(title = "ES批量删除数据", businessType = BusinessType.DELETE)
@DeleteMapping("/batch-delete")
public R<Integer> batchDelete(@RequestParam(required = false) Long storeId) {
@ -51,7 +51,7 @@ public class ElasticSearchController extends XktBaseController {
return R.ok();
}
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@PreAuthorize("@ss.hasAnyRoles('admin')")
@Log(title = "ES批量删除数据特定商品", businessType = BusinessType.DELETE)
@DeleteMapping("/prod/batch-delete")
public R<Integer> batchDeleteProd(@Validated @RequestBody EsProdBatchDeleteVO deleteVO) {

View File

@ -117,7 +117,7 @@ spring:
druid:
# 主库数据源
master:
url: jdbc:mysql://127.0.0.1:3306/xiekutong?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
url: jdbc:mysql://127.0.0.1:3306/cdbuju?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
# password: xvV@1WaZbkjSJjRO
password: 123456

View File

@ -90,6 +90,11 @@ public class CacheConstants {
*/
public static final String STORE_KEY = "store:";
/**
*
*/
public static final String STORE_LIST_KEY = "store_list";
/**
* 广
*/

View File

@ -183,9 +183,10 @@ public class XktTask {
if (CollectionUtils.isEmpty(storeList)) {
return;
}
storeList.forEach(store -> {
redisCache.setCacheObject(CacheConstants.STORE_KEY + store.getId(), store);
});
// 单个档口到redis中
storeList.forEach(store -> redisCache.setCacheObject(CacheConstants.STORE_KEY + store.getId(), store));
// 所有正在生效的档口
redisCache.setCacheObject(CacheConstants.STORE_LIST_KEY, storeList.stream().map(Store::getId).map(String::valueOf).collect(Collectors.toList()));
}
/**

View File

@ -3,6 +3,7 @@ package com.ruoyi.xkt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.xkt.domain.StoreProduct;
import com.ruoyi.xkt.dto.dailyStoreTag.DailyStoreTagDTO;
import com.ruoyi.xkt.dto.picture.ProductMatchDTO;
import com.ruoyi.xkt.dto.storeHomepage.StoreRecommendResDTO;
import com.ruoyi.xkt.dto.storeProduct.*;
import org.apache.ibatis.annotations.Param;
@ -139,5 +140,13 @@ public interface StoreProductMapper extends BaseMapper<StoreProduct> {
*/
StoreProdPcDownloadInfoResDTO selectDownloadProdInfo(@Param("storeProdId") Long storeProdId);
/**
*
*
* @param storeProdIdList ID
* @return List<ProductMatchDTO>
*/
List<ProductMatchDTO> filterInvalidStoreProd(@Param("storeProdIdList") List<Long> storeProdIdList);
}

View File

@ -9,11 +9,14 @@ import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.page.Page;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.es.EsClientWrapper;
import com.ruoyi.framework.notice.fs.FsNotice;
import com.ruoyi.xkt.domain.Store;
@ -65,6 +68,7 @@ public class ElasticSearchServiceImpl implements IElasticSearchService {
final EsClientWrapper esClientWrapper;
final StoreProductFileMapper prodFileMapper;
final FsNotice fsNotice;
final RedisCache redisCache;
@Value("${es.indexName}")
private String ES_INDEX_NAME;
@ -77,6 +81,10 @@ public class ElasticSearchServiceImpl implements IElasticSearchService {
@Override
@Transactional
public void batchCreate(Long storeId) {
// 用户是否为超级管理员
if (!SecurityUtils.isSuperAdmin()) {
throw new ServiceException("当前用户非超级管理员,无权限操作!", HttpStatus.ERROR);
}
LambdaQueryWrapper<StoreProduct> wrapper = new LambdaQueryWrapper<StoreProduct>()
.eq(StoreProduct::getDelFlag, Constants.UNDELETED);
if (ObjectUtils.isNotEmpty(storeId)) {
@ -99,6 +107,10 @@ public class ElasticSearchServiceImpl implements IElasticSearchService {
@Override
@Transactional
public void batchCreateProd(EsProdBatchCreateDTO createProdDTO) {
// 用户是否为超级管理员
if (!SecurityUtils.isSuperAdmin()) {
throw new ServiceException("当前用户非超级管理员,无权限操作!", HttpStatus.ERROR);
}
LambdaQueryWrapper<StoreProduct> wrapper = new LambdaQueryWrapper<StoreProduct>()
.eq(StoreProduct::getDelFlag, Constants.UNDELETED).eq(StoreProduct::getStoreId, createProdDTO.getStoreId())
.in(StoreProduct::getId, createProdDTO.getStoreProdIdList());
@ -119,6 +131,10 @@ public class ElasticSearchServiceImpl implements IElasticSearchService {
@Override
@Transactional
public void batchDelete(Long storeId) {
// 用户是否为超级管理员
if (!SecurityUtils.isSuperAdmin()) {
throw new ServiceException("当前用户非超级管理员,无权限操作!", HttpStatus.ERROR);
}
LambdaQueryWrapper<StoreProduct> queryWrapper = new LambdaQueryWrapper<StoreProduct>()
.eq(StoreProduct::getDelFlag, Constants.UNDELETED);
if (ObjectUtils.isNotEmpty(storeId)) {
@ -141,6 +157,10 @@ public class ElasticSearchServiceImpl implements IElasticSearchService {
@Override
@Transactional
public void batchDeleteProd(EsProdBatchDeleteDTO deleteDTO) {
// 用户是否为超级管理员
if (!SecurityUtils.isSuperAdmin()) {
throw new ServiceException("当前用户非超级管理员,无权限操作!", HttpStatus.ERROR);
}
LambdaQueryWrapper<StoreProduct> queryWrapper = new LambdaQueryWrapper<StoreProduct>()
.eq(StoreProduct::getDelFlag, Constants.UNDELETED).eq(StoreProduct::getStoreId, deleteDTO.getStoreId())
.in(StoreProduct::getId, deleteDTO.getStoreProdIdList());
@ -197,15 +217,30 @@ public class ElasticSearchServiceImpl implements IElasticSearchService {
// 将搜索条件添加到主查询
boolQueryBuilder.must(searchBoolQuery.build()._toQuery());
}
// 档口ID 过滤条件
// 处理逻辑 获取所有可用的档口,如果该档口是停用状态,则不返回该档口的任何数据
List<String> existStoreIdList = this.redisCache.getCacheObject(CacheConstants.STORE_LIST_KEY);
List<String> effectiveStoreIds = null;
if (CollectionUtils.isNotEmpty(searchDTO.getStoreIdList())) {
// 如果查询条件中有指定档口则过滤掉不在existStoreIdList中的档口
effectiveStoreIds = CollectionUtils.isEmpty(existStoreIdList) ? searchDTO.getStoreIdList()
: searchDTO.getStoreIdList().stream().filter(existStoreIdList::contains).collect(Collectors.toList());
} else {
// 如果查询条件中没有指定档口,则使用所有可用档口
if (CollectionUtils.isNotEmpty(existStoreIdList)) {
effectiveStoreIds = new ArrayList<>(existStoreIdList);
}
}
// 档口ID 过滤条件
if (CollectionUtils.isNotEmpty(effectiveStoreIds)) {
TermsQueryField termsQueryField = new TermsQueryField.Builder()
.value(searchDTO.getStoreIdList().stream()
.value(effectiveStoreIds.stream()
.map(FieldValue::of)
.collect(Collectors.toList()))
.build();
boolQueryBuilder.filter(f -> f.terms(t -> t.field("storeId").terms(termsQueryField)));
}
// 添加prodStatus 过滤条件
if (CollectionUtils.isNotEmpty(searchDTO.getProdStatusList())) {
TermsQueryField termsQueryField = new TermsQueryField.Builder()

View File

@ -97,8 +97,18 @@ public class PictureSearchServiceImpl implements IPictureSearchService {
final List<Long> storeProdIdList = picSearchAdverts.stream().map(x -> x.getStoreProdId()).collect(Collectors.toList());
// 搜索结果过滤掉广告商品
List<ProductMatchDTO> filterResults = results.stream().filter(x -> !storeProdIdList.contains(x.getStoreProductId())).collect(Collectors.toList());
if (CollectionUtils.isEmpty(filterResults)) {
return BeanUtil.copyToList(picSearchAdverts, StoreProdViewDTO.class);
}
// 过滤掉无效的档口,有可能该档口没有续费之类的,被下架了
List<ProductMatchDTO> trueResultList = this.storeProdMapper.filterInvalidStoreProd(filterResults.stream()
.map(ProductMatchDTO::getStoreProductId).distinct().collect(Collectors.toList()));
// 过滤掉无效的商品之后,是否还剩下商品
if (CollectionUtils.isEmpty(trueResultList)) {
return BeanUtil.copyToList(picSearchAdverts, StoreProdViewDTO.class);
}
// 档口商品显示的基本属性 数据库筛选必须要带prodStatus因为图搜搜出来的可能是下架的商品
List<StoreProdViewDTO> storeProdViewAttrList = this.storeProdMapper.getStoreProdViewAttr(filterResults.stream()
List<StoreProdViewDTO> storeProdViewAttrList = this.storeProdMapper.getStoreProdViewAttr(trueResultList.stream()
.map(ProductMatchDTO::getStoreProductId).distinct().collect(Collectors.toList()),
java.sql.Date.valueOf(LocalDate.now().minusMonths(2)), java.sql.Date.valueOf(LocalDate.now()));
// 设置商品标签

View File

@ -4,7 +4,6 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import co.elastic.clients.elasticsearch.core.BulkResponse;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -22,7 +21,6 @@ import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bigDecimal.CollectorsUtil;
import com.ruoyi.framework.es.EsClientWrapper;
import com.ruoyi.framework.sms.SmsClientWrapper;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.xkt.domain.*;
@ -128,7 +126,21 @@ public class StoreServiceImpl implements IStoreService {
.eq(Store::getId, delFlagDTO.getStoreId())))
.orElseThrow(() -> new ServiceException("档口不存在!", HttpStatus.ERROR));
store.setDelFlag(delFlagDTO.getDelFlag() ? Constants.UNDELETED : Constants.DELETED);
return storeMapper.updateById(store);
int count = storeMapper.updateById(store);
if (delFlagDTO.getDelFlag()) {
// 如果为启用则重新添加到redis中
redisCache.setCacheObject(CacheConstants.STORE_KEY + store.getId(), store);
} else {
// 如果为停用则从redis中删除
redisCache.deleteObject(CacheConstants.STORE_KEY + store.getId());
}
// 获取所有的档口并且存到redis中
List<Store> storeList = this.storeMapper.selectList(new LambdaQueryWrapper<Store>()
.eq(Store::getDelFlag, Constants.UNDELETED));
if (CollectionUtils.isNotEmpty(storeList)) {
redisCache.setCacheObject(CacheConstants.STORE_LIST_KEY, storeList.stream().map(Store::getId).map(String::valueOf).collect(Collectors.toList()));
}
return count;
}
/**

View File

@ -332,5 +332,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
sp.del_flag = 0 AND sp.id = #{storeProdId}
</select>
<select id="filterInvalidStoreProd">
SELECT
sp.id AS storeProductId
FROM
store_product sp JOIN store s ON sp.store_id = s.id AND s.del_flag = 0
WHERE
sp.del_flag = 0 AND sp.private_item = 0
<if test="storeProdIdList != null">
AND sp.id IN
<foreach item="item" collection="storeProdIdList" index="index" open="(" close=")" separator=",">
#{item}
</foreach>
</if>
</select>
</mapper>