springboot+redis實現熱詞搜尋推薦(Java)
阿新 • • 發佈:2019-02-11
import cc.datebook.common.JsonResult;
import cc.datebook.entity.BookInfo;
import cc.datebook.enums.ResultCode;
import cc.datebook.service.BookInfoService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation .Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.RequestBody ;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.*;
@RestController
@RequestMapping("/hotKey")
public class HotKeyController {
private Logger logger = LoggerFactory.getLogger (this.getClass());
@Resource(name = "redisKeyDatabase")
private RedisTemplate redisKeyDatabase;
@Resource(name = "redisKeyTimeDatabase")
private RedisTemplate redisKeyTimeDatabase;
@Autowired
private BookInfoService bookInfoService;
/**
* 手動匯入若干資料以供測試
*/
@RequestMapping(value = "/add", method = RequestMethod.POST)
public JsonResult redisAdd() {
List<BookInfo> bookInfos = bookInfoService.getBookInfos();
for (BookInfo bookInfo : bookInfos) {
if (StringUtils.isNotBlank(bookInfo.getAuthor())) {
String author = bookInfo.getAuthor().replaceAll("\\﹝.*?\\﹞|\\〔.*?\\〕|\\(.*?\\)|\\{.*?}|\\[.*?]|\\[.*?]|\\【.*?】|(.*?)|等|著|編者|主編|[^0-9a-zA-Z\u4e00-\u9fa5.,,•·《 》]", "").trim();
author = author.replaceAll("\\s+", " ").trim();
try {
if (author.endsWith(",") || author.endsWith(",")) {
author = author.substring(0, author.length() - 1);
}
} catch (Exception e) {
logger.error("1111111" + bookInfo.toString());
}
try {
String tem = author.substring(author.lastIndexOf(",") + 1, author.length());
String tem1 = author.substring(author.lastIndexOf(",") + 1, author.length());
if (StringUtils.isBlank(tem)) {
author = author.substring(0, author.lastIndexOf(","));
}
if (StringUtils.isBlank(tem1)) {
author = author.substring(0, author.lastIndexOf(","));
}
} catch (Exception e) {
logger.error("2222222" + bookInfo.toString());
}
bookInfo.setAuthor(author);
bookInfoService.updateByPrimaryKeySelective(bookInfo);
}
}
Long now = System.currentTimeMillis();
ZSetOperations zSetOperations = redisKeyDatabase.opsForZSet();
ValueOperations<String, Long> valueOperations = redisKeyTimeDatabase.opsForValue();
List<String> title = bookInfoService.getBookTitle();
List<String> author = bookInfoService.getBookAuthor();
for (int i = 0, lengh = title.size(); i < lengh; i++) {
String tle = title.get(i);
try {
if (zSetOperations.score("title", tle) <= 0) {
zSetOperations.add("title", tle, 0);
valueOperations.set(tle, now);
}
} catch (Exception e) {
zSetOperations.add("title", tle, 0);
valueOperations.set(tle, now);
}
}
for (int i = 0, lengh = author.size(); i < lengh; i++) {
String aut = author.get(i);
if (StringUtils.isNotBlank(aut)) {
String auth[] = aut.split(",|,");
for (String str : auth) {
if (StringUtils.isNotBlank(str)) {
try {
if (zSetOperations.score("title", str.trim()) <= 0) {
zSetOperations.add("title", str.trim(), 0);
valueOperations.set(str.trim(), now);
}
} catch (Exception e) {
zSetOperations.add("title", str.trim(), 0);
valueOperations.set(str.trim(), now);
}
}
}
}
}
return new JsonResult(ResultCode.SUCCESS, "成功");
}
/**
* 根據key搜尋相關最熱的前十名
*/
@RequestMapping(value = "/get", method = RequestMethod.POST)
public JsonResult redisGet(@RequestBody Map<String, Object> params) {
String key = params.get("key").toString();
Long now = System.currentTimeMillis();
List<String> result = new ArrayList<>();
ZSetOperations zSetOperations = redisKeyDatabase.opsForZSet();
ValueOperations<String, Long> valueOperations = redisKeyTimeDatabase.opsForValue();
Set<String> value = zSetOperations.reverseRangeByScore("title", 0, Double.MAX_VALUE);
//key不為空的時候 推薦相關的最熱前十名
for (String val : value) {
if (StringUtils.containsIgnoreCase(val, key)) {
if (result.size() > 9) {//只返回最熱的前十名
break;
}
Long time = valueOperations.get(val);
if ((now - time) < 2592000000L) {//返回最近一個月的資料
result.add(val);
} else {//時間超過一個月沒搜尋就把這個詞熱度歸0
zSetOperations.add("title", val, 0);
}
}
}
return new JsonResult(ResultCode.SUCCESS, "成功", result);
}
/**
* 每次點選給相關詞熱度+1
*/
@RequestMapping(value = "/incrementScore", method = RequestMethod.POST)
public JsonResult incrementScore(@RequestBody Map<String, Object> params) {
String key = params.get("key").toString();
Long now = System.currentTimeMillis();
ZSetOperations zSetOperations = redisKeyDatabase.opsForZSet();
ValueOperations<String, Long> valueOperations = redisKeyTimeDatabase.opsForValue();
zSetOperations.incrementScore("title", key, 1);
valueOperations.getAndSet(key, now);
return new JsonResult(ResultCode.SUCCESS, "成功");
}
}