Redis構建文章聚合資訊分類網站
阿新 • • 發佈:2018-11-25
本系列教程內容提要
Java工程師之Redis實戰系列教程教程是一個學習教程,是關於Java工程師的Redis知識的實戰系列教程,本系列教程均以解決特定問題為目標,使用Redis快速解決在實際生產中的相關問題,為了更方便的與大家一起探討與學習,每個章節均提供儘可能詳細的示例原始碼及註釋,所有示例原始碼均可在javacourse-redis-in-action找到相關幫助!
你思考過這個問題嗎?
如果你想過自己開發一個論壇網站,或者文章網站?最起碼想過開發自己的部落格網站吧?那麼你是否考慮過這個問題--“當你資料庫查詢你的記錄時,你考慮過這些記錄應當以什麼樣的方式展現在網頁?按釋出時間?按瀏覽次數?
- 按釋出時間(嗯,應當時沒問題的...)
- 按瀏覽次數(嗯,如果給定一個時間範圍也是沒問題的...)
你是否瀏覽過stackoverflow,如下圖所示,你是否考慮過這些記錄時按照什麼展現的呢?唔...經過你的長久思考後,你想“應該不是最新,也不是瀏覽最多,應該時經過一系列的機制後算出來的....”
我們通過什麼機制進行排序呢?
既然你能想到一定是經過一系列的運算過程的出來的排序過程,那麼我們可否設計一個符合我們自己網站的 "運算過程" 呢? 我們規定:
- 文章的釋出時間+A支援票乘以常量E-B反對票乘以常量E
- 文章7天后不再支援投支援票/反對票
設計Redis表結構
表名 | 結構 |
---|---|
文章 | HASH |
投票人 | SET |
群組 | SET |
文章評分排行 | ZSET |
文章最新排行 | ZSET |
群組最新文章 | ZSET |
群組評分排行 | ZSET |
核心原始碼
查詢文章 (查詢功能做的最多的就是拼裝資料,但是在查詢某個群組的文章的時候,就是涉及到了Redis的交集運算)
/** * 獲得所有文章列表文章列表 * * @param page 頁數 * @param order 排序 * @param model 模型 * @return */ @GetMapping(value = "/getArticleList") public String getArticle(@RequestParam(required = false, defaultValue = "1") Integer page, @RequestParam(required = false, defaultValue = "score") String order, Model model) { /*獲取文章列表*/ List<Article> articleArrayList = getArticles(jedis, page, order + ":"); /*拼裝分頁資訊*/ model.addAttribute("articleArrayList", articleArrayList); model.addAttribute("order", order); model.addAttribute("page", page); return "index"; }
/**
* 獲取分組文章列表
*
* @return
*/
@GetMapping(value = "/getGroupArticleList")
public String getGroupArticle(@RequestParam(required = false, defaultValue = "1") Integer page,
@RequestParam(required = false, defaultValue = "score") String order,
@RequestParam(required = true) String group, Model model) {
List<Article> groupArticles = getGroupArticles(jedis, group, page, order + ":");
/*拼裝分頁資訊*/
model.addAttribute("groupArticles", groupArticles);
model.addAttribute("group", group);
model.addAttribute("order", order);
model.addAttribute("page", page);
return "group";
}
釋出文章 (釋出文章需要注意的是根據文章的所屬群組,將其新增至相關群組)
/**
* 釋出文章
*
* @param article
* @param model
* @return
*/
@PostMapping(value = "/addArticle")
public String addArticle(Article article, Model model) {
/*模擬使用者*/
User user = getUser();
/*從Redis獲取文章的自增ID*/
String id = String.valueOf(jedis.incr("article:"));
/*將文章的發帖人本人新增至投票列表*/
String voted = "voted:" + id;
jedis.sadd(voted, user.getUserId().toString());
jedis.expire(voted, ONE_WEEK_IN_SECONDS);
/*將文章新增至文章列表*/
long now = System.currentTimeMillis() / 1000;
String articleId = "article:" + id;
HashMap<String, String> articleData = new HashMap<>();
articleData.put("title", article.getTitle());
articleData.put("link", article.getLink());
articleData.put("user", user.getUserId().toString());
articleData.put("time", String.valueOf(now));
articleData.put("votes", "1");
articleData.put("group", article.getGroup());
articleData.put("opposeVotes", "0");
jedis.hmset(articleId, articleData);
/*將文章新增至分值列表*/
jedis.zadd("score:", now + VOTE_SCORE, articleId);
/*將文章新增至釋出時間列表*/
jedis.zadd("time:", now, articleId);
/*將文章加入其所屬分組*/
addGroup(jedis, articleId, new String[]{article.getGroup()});
/*設定模型資料*/
model.addAttribute("page", 1);
model.addAttribute("order", "score");
return "redirect:/article/getArticleList";
}
投票 (根據我們前面的規定,7天后不再提供對該文章的投票功能,所以需要在進行投票之前注意文章的釋出時間)
/**
* 投票
*
* @param articleId
* @param model
* @return
*/
@GetMapping(value = "/articleVote")
public String articleVote(Integer articleId, int tag, RedirectAttributes model) {
/*模擬使用者*/
User user = getUser();
String result = article_vote(jedis, user, articleId, tag);
/*設定模型資料*/
model.addFlashAttribute("result", result);
model.addFlashAttribute("page", 1);
model.addFlashAttribute("order", "score");
return "redirect:/article/getArticleList";
}
執行效果圖
各位友友可以下載本章的示例原始碼,執行訪問 http://localhost:8080/article/getArticleList
本章原始碼提供完整的執行環境原始碼GitHub下載