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

Redis構建文章聚合信息分類網站

運行環境 alt result order val attribute return def tle

本系列教程內容提要

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

Redis構建文章聚合信息分類網站