1. 程式人生 > >Redis構建文章聚合資訊分類網站

Redis構建文章聚合資訊分類網站

本系列教程內容提要

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下載