master:系统搜索及热搜功能完善;
parent
59ac41fffb
commit
3810784aab
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 每晚凌晨3点更新系统热搜到redis中
|
||||
*/
|
||||
@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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ public class UserSearchHistory extends XktBaseEntity {
|
|||
*/
|
||||
private Integer platformId;
|
||||
/**
|
||||
* 统计时间
|
||||
* 搜索时间
|
||||
*/
|
||||
private Date voucherDate;
|
||||
private Date searchTime;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue