From 3810784aab0e82dd27ed41cf09f51d050da7727f Mon Sep 17 00:00:00 2001 From: liujiang <569804566@qq.com> Date: Sun, 1 Jun 2025 00:19:54 +0800 Subject: [PATCH] =?UTF-8?q?master=EF=BC=9A=E7=B3=BB=E7=BB=9F=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E5=8F=8A=E7=83=AD=E6=90=9C=E5=8A=9F=E8=83=BD=E5=AE=8C?= =?UTF-8?q?=E5=96=84=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/controller/xkt/WebsiteController.java | 1 + .../ruoyi/common/constant/CacheConstants.java | 5 +- .../ruoyi/common/core/redis/RedisCache.java | 22 +++++-- .../controller/DailyTaskController.java | 8 ++- .../java/com/ruoyi/quartz/task/XktTask.java | 58 ++++++++++++++----- .../ruoyi/xkt/domain/UserSearchHistory.java | 4 +- .../xkt/mapper/UserSearchHistoryMapper.java | 16 +++++ .../ruoyi/xkt/service/IWebsiteAPPService.java | 1 + .../ruoyi/xkt/service/IWebsitePCService.java | 1 + .../service/impl/WebsiteAPPServiceImpl.java | 3 +- .../service/impl/WebsitePCServiceImpl.java | 4 +- 11 files changed, 99 insertions(+), 24 deletions(-) create mode 100644 xkt/src/main/java/com/ruoyi/xkt/mapper/UserSearchHistoryMapper.java diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/WebsiteController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/WebsiteController.java index f07385427..92d0bd878 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/WebsiteController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/WebsiteController.java @@ -37,6 +37,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.io.IOException; +import java.text.ParseException; import java.util.List; /** diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java index e5fed0963..d52e05e4c 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java @@ -219,6 +219,9 @@ public class CacheConstants { * 用户搜索历史 */ public static final String USER_SEARCH_HISTORY = "user_search_history:"; - + /** + * 系统前20条热搜 + */ + public static final String SEARCH_HOT_KEY = "search_hot_key"; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java index 96ce2e4ca..b513bed2e 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java @@ -1,10 +1,7 @@ package com.ruoyi.common.core.redis; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.BoundSetOperations; -import org.springframework.data.redis.core.HashOperations; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.ValueOperations; +import org.springframework.data.redis.core.*; import org.springframework.stereotype.Component; import java.util.*; @@ -268,6 +265,23 @@ public class RedisCache return redisTemplate.keys(pattern); } + /** + * 数据量大时,模糊匹配keys + * + * @param pattern 字符串前缀 + * @return 对象列表 + */ + public Collection scanKeys(final String pattern) { + Set keys = new HashSet<>(); + ScanOptions options = ScanOptions.scanOptions().match(pattern).build(); + Cursor cursor = redisTemplate.getConnectionFactory().getConnection().scan(options); + while (cursor.hasNext()) { + keys.add(new String(cursor.next())); + } + return keys; + } + + public boolean exists(final String key) { return redisTemplate.hasKey(key); } diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/DailyTaskController.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/DailyTaskController.java index 19d0deb80..93fe366ae 100644 --- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/DailyTaskController.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/DailyTaskController.java @@ -91,11 +91,17 @@ public class DailyTaskController extends BaseController { } @PostMapping("/symbol-redis") - public R saveSymbolToRedis(SysJob sysJob) throws ParseException { + public R saveSymbolToRedis(SysJob sysJob) { task.saveSymbolToRedis(); return R.ok(); } + @PostMapping("/user-search-history") + public R dailyUserSearchHistory(SysJob sysJob) { + task.dailyUpdateUserSearchHistory(); + return R.ok(); + } + } diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java index 9d585bf56..c6532faae 100644 --- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java @@ -29,6 +29,7 @@ import com.ruoyi.xkt.dto.dailyStoreTag.DailyStoreTagDTO; import com.ruoyi.xkt.dto.order.StoreOrderCancelDTO; import com.ruoyi.xkt.dto.order.StoreOrderRefund; import com.ruoyi.xkt.dto.storeProductFile.StoreProdFileLatestFourProdDTO; +import com.ruoyi.xkt.dto.useSearchHistory.UserSearchHistoryDTO; import com.ruoyi.xkt.enums.*; import com.ruoyi.xkt.manager.PaymentManager; import com.ruoyi.xkt.mapper.*; @@ -93,6 +94,7 @@ public class XktTask { final PictureSearchMapper pictureSearchMapper; final StoreProductStatisticsMapper storeProdStatMapper; final StoreProductFileMapper storeProdFileMapper; + final UserSearchHistoryMapper userSearchHisMapper; /** * 定时任务上市季节年份 @@ -578,26 +580,54 @@ public class XktTask { * 每天凌晨2点更新用户搜索历史入库 */ @Transactional - public void dailyUpdateUserSearchHistory(){ - - // TODO - // TODO - // TODO - // TODO - + public void dailyUpdateUserSearchHistory() { + Collection keyList = this.redisCache.scanKeys(CacheConstants.USER_SEARCH_HISTORY + "*"); + if (CollectionUtils.isEmpty(keyList)) { + return; + } + List redisSearchList = new ArrayList<>(); + keyList.forEach(key -> { + List tempList = this.redisCache.getCacheObject(key); + CollectionUtils.addAll(redisSearchList, tempList); + }); + // 用户最新搜索列表 + List insertSearchList = redisSearchList.stream().filter(x -> ObjectUtils.isEmpty(x.getId())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(insertSearchList)) { + return; + } + this.userSearchHisMapper.insert(BeanUtil.copyToList(insertSearchList, UserSearchHistory.class)); + // 将最新的数据更新到redis中 + List latestSearchList = this.userSearchHisMapper.selectList(new LambdaQueryWrapper() + .eq(UserSearchHistory::getDelFlag, Constants.UNDELETED)); + latestSearchList.stream().collect(Collectors.groupingBy(UserSearchHistory::getUserId)) + .forEach((userId, list) -> { + // 获取用户最新搜索的20条数据 + list = list.stream().sorted(Comparator.comparing(UserSearchHistory::getSearchTime).reversed()).limit(20).collect(Collectors.toList()); + redisCache.setCacheObject(CacheConstants.USER_SEARCH_HISTORY + userId, BeanUtil.copyToList(list, UserSearchHistoryDTO.class)); + }); } /** * 每晚凌晨3点更新系统热搜到redis中 */ @Transactional - public void dailyUpdateSearchHotToRedis(){ - - // TODO - // TODO - // TODO - // TODO - + public void dailyUpdateSearchHotToRedis() { + Collection keyList = this.redisCache.scanKeys(CacheConstants.USER_SEARCH_HISTORY + "*"); + if (CollectionUtils.isEmpty(keyList)) { + return; + } + List redisSearchList = new ArrayList<>(); + keyList.forEach(key -> { + List tempList = this.redisCache.getCacheObject(key); + CollectionUtils.addAll(redisSearchList, tempList); + }); + Map searchCountMap = redisSearchList.stream().collect(Collectors.groupingBy(UserSearchHistoryDTO::getSearchContent, + Collectors.summingLong(UserSearchHistoryDTO::getId))); + // searchCountMap 按照 value 大小倒序排,取前20条热搜 + List> top20List = searchCountMap.entrySet().stream().sorted(Map.Entry.comparingByValue().reversed()) + .limit(20).collect(Collectors.toList()); + List top20Keys = top20List.stream().map(Map.Entry::getKey).collect(Collectors.toList()); + redisCache.setCacheObject(CacheConstants.SEARCH_HOT_KEY, top20Keys); } diff --git a/xkt/src/main/java/com/ruoyi/xkt/domain/UserSearchHistory.java b/xkt/src/main/java/com/ruoyi/xkt/domain/UserSearchHistory.java index 1e329351d..d241cc955 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/domain/UserSearchHistory.java +++ b/xkt/src/main/java/com/ruoyi/xkt/domain/UserSearchHistory.java @@ -43,8 +43,8 @@ public class UserSearchHistory extends XktBaseEntity { */ private Integer platformId; /** - * 统计时间 + * 搜索时间 */ - private Date voucherDate; + private Date searchTime; } diff --git a/xkt/src/main/java/com/ruoyi/xkt/mapper/UserSearchHistoryMapper.java b/xkt/src/main/java/com/ruoyi/xkt/mapper/UserSearchHistoryMapper.java new file mode 100644 index 000000000..d4e976c49 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/mapper/UserSearchHistoryMapper.java @@ -0,0 +1,16 @@ +package com.ruoyi.xkt.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.xkt.domain.UserSearchHistory; +import org.springframework.stereotype.Repository; + +/** + * 档口Mapper接口 + * + * @author ruoyi + * @date 2025-03-26 + */ +@Repository +public interface UserSearchHistoryMapper extends BaseMapper { + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IWebsiteAPPService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IWebsiteAPPService.java index 7e9bcbf19..061daa97a 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IWebsiteAPPService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IWebsiteAPPService.java @@ -8,6 +8,7 @@ import com.ruoyi.xkt.dto.es.ESProductDTO; import com.ruoyi.xkt.dto.website.IndexSearchDTO; import java.io.IOException; +import java.text.ParseException; import java.util.List; /** diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCService.java index 29d026f95..3148df104 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCService.java @@ -15,6 +15,7 @@ import com.ruoyi.xkt.dto.website.IndexSearchDTO; import com.ruoyi.xkt.dto.website.StoreSearchDTO; import java.io.IOException; +import java.text.ParseException; import java.util.List; /** diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsiteAPPServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsiteAPPServiceImpl.java index 3608da776..7351c58d8 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsiteAPPServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsiteAPPServiceImpl.java @@ -41,6 +41,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.IOException; +import java.text.ParseException; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -757,7 +758,7 @@ public class WebsiteAPPServiceImpl implements IWebsiteAPPService { // 获取用户在redis中的搜索数据 List userSearchList = CollUtil.defaultIfEmpty(redisCache.getCacheObject(CacheConstants.USER_SEARCH_HISTORY + loginUser.getUserId()), new ArrayList<>()); userSearchList.add(new UserSearchHistoryDTO().setUserId(loginUser.getUserId()).setUserName(loginUser.getUser().getNickName()).setSearchContent(search) - .setPlatformId(SearchPlatformType.APP.getValue()).setSearchTime(DateUtils.getNowDate())); + .setPlatformId(SearchPlatformType.APP.getValue()).setSearchTime(new Date())); // 设置用户搜索历史,不过期 redisCache.setCacheObject(CacheConstants.USER_SEARCH_HISTORY + loginUser.getUserId(), userSearchList); } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCServiceImpl.java index 80551e0ed..fd1e1a9bc 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCServiceImpl.java @@ -2,6 +2,7 @@ package com.ruoyi.xkt.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import co.elastic.clients.elasticsearch._types.FieldValue; import co.elastic.clients.elasticsearch._types.query_dsl.*; @@ -54,6 +55,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.IOException; +import java.text.ParseException; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -1721,7 +1723,7 @@ public class WebsitePCServiceImpl implements IWebsitePCService { // 获取用户在redis中的搜索数据 List userSearchList = CollUtil.defaultIfEmpty(redisCache.getCacheObject(CacheConstants.USER_SEARCH_HISTORY + loginUser.getUserId()), new ArrayList<>()); userSearchList.add(new UserSearchHistoryDTO().setUserId(loginUser.getUserId()).setUserName(loginUser.getUser().getNickName()).setSearchContent(search) - .setPlatformId(SearchPlatformType.PC.getValue()).setSearchTime(DateUtils.getNowDate())); + .setPlatformId(SearchPlatformType.PC.getValue()).setSearchTime(new Date())); // 设置用户搜索历史,不过期 redisCache.setCacheObject(CacheConstants.USER_SEARCH_HISTORY + loginUser.getUserId(), userSearchList); }