master:系统搜索及热搜功能完善;

pull/1121/head
liujiang 2025-06-01 00:19:54 +08:00
parent 59ac41fffb
commit 3810784aab
11 changed files with 99 additions and 24 deletions

View File

@ -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;
/**

View File

@ -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";
}

View File

@ -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<String> scanKeys(final String pattern) {
Set<String> keys = new HashSet<>();
ScanOptions options = ScanOptions.scanOptions().match(pattern).build();
Cursor<byte[]> 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);
}

View File

@ -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();
}
}

View File

@ -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<String> keyList = this.redisCache.scanKeys(CacheConstants.USER_SEARCH_HISTORY + "*");
if (CollectionUtils.isEmpty(keyList)) {
return;
}
List<UserSearchHistoryDTO> redisSearchList = new ArrayList<>();
keyList.forEach(key -> {
List<UserSearchHistoryDTO> tempList = this.redisCache.getCacheObject(key);
CollectionUtils.addAll(redisSearchList, tempList);
});
// 用户最新搜索列表
List<UserSearchHistoryDTO> 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<UserSearchHistory> latestSearchList = this.userSearchHisMapper.selectList(new LambdaQueryWrapper<UserSearchHistory>()
.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));
});
}
/**
* 3redis
*/
@Transactional
public void dailyUpdateSearchHotToRedis(){
// TODO
// TODO
// TODO
// TODO
public void dailyUpdateSearchHotToRedis() {
Collection<String> keyList = this.redisCache.scanKeys(CacheConstants.USER_SEARCH_HISTORY + "*");
if (CollectionUtils.isEmpty(keyList)) {
return;
}
List<UserSearchHistoryDTO> redisSearchList = new ArrayList<>();
keyList.forEach(key -> {
List<UserSearchHistoryDTO> tempList = this.redisCache.getCacheObject(key);
CollectionUtils.addAll(redisSearchList, tempList);
});
Map<String, Long> searchCountMap = redisSearchList.stream().collect(Collectors.groupingBy(UserSearchHistoryDTO::getSearchContent,
Collectors.summingLong(UserSearchHistoryDTO::getId)));
// searchCountMap 按照 value 大小倒序排取前20条热搜
List<Map.Entry<String, Long>> top20List = searchCountMap.entrySet().stream().sorted(Map.Entry.<String, Long>comparingByValue().reversed())
.limit(20).collect(Collectors.toList());
List<String> top20Keys = top20List.stream().map(Map.Entry::getKey).collect(Collectors.toList());
redisCache.setCacheObject(CacheConstants.SEARCH_HOT_KEY, top20Keys);
}

View File

@ -43,8 +43,8 @@ public class UserSearchHistory extends XktBaseEntity {
*/
private Integer platformId;
/**
*
*
*/
private Date voucherDate;
private Date searchTime;
}

View File

@ -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<UserSearchHistory> {
}

View File

@ -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;
/**

View File

@ -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;
/**

View File

@ -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<UserSearchHistoryDTO> 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);
}

View File

@ -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<UserSearchHistoryDTO> 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);
}