基于Redis实现点赞、排序(排行榜)功能(ZSet集合)

代码如下(简单明了,直接复制粘贴使用):

package com.pipilin.api.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pipilin.common.core.controller.BaseController;
import com.pipilin.common.core.domain.AjaxResult;
import com.pipilin.vim.domain.Article;
import com.pipilin.vim.service.ArticleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @title: 文章
 * @author: 289151517520@qq.com
 * @date: 2022/7/11 9:49
 */

@RestController
@RequestMapping("/system/like")
public class PArticleController extends BaseController {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ArticleService articleService;


    /**
     * @title: 文章分页
     * @params: page 分页对象 articleId 文章ID
     * @date: 2022/7/9 21:41
     */
    @GetMapping("/queryArticleList")
    public AjaxResult queryArticleList(Page page, Long articleId) {
        Page page1 = articleService.page(page, new LambdaQueryWrapper<Article>().orderByDesc(Article::getLiked));
        List<Article> records = page1.getRecords();
        records.forEach(article -> {
            articleService.queryArticleUser(article);
            isArticleLiked(article);
        });
        return AjaxResult.success(records);
    }


    /**
     * @title: 文章详情
     * @params: articleId 文章ID
     * @date: 2022/7/9 21:41
     */
    @GetMapping("/queryArticleById")
    public AjaxResult queryArticleById(Long articleId) {

        // 1.查询article
        Article article = articleService.getById(articleId);
        if (ObjectUtil.isNull(article)) {
            return AjaxResult.error("文章不存在!");
        }
        // 2. 查询article有关的用户
        List<Article> articles = articleService.queryArticleUser(article);
        // 3. 查询article是否被点赞
        isArticleLiked(article);
        return AjaxResult.success(article);
    }

    /**
     * @title: 文章是否点赞
     * @params: articleId 文章ID
     * @date: 2022/7/9 21:42
     */
    private void isArticleLiked(Article article) {
        // 1.获取登录用户ID
        Long userId = getUserId();
        // 1.2用户未登录,无需查询是否点赞
        if (userId == null) {
            return;
        }
        // 2.判断当前登录用户是否已经点赞
        String key = "article:liked:" + article.getId();
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        article.setLiked(BooleanUtil.isTrue(ObjectUtil.isNotNull(score)));
    }


    /**
     * @title: 文章点赞、取消点赞
     * @params: articleId 文章ID
     * @date: 2022/7/9 21:09
     */
    @PostMapping
    public AjaxResult likedArticle(Long articleId) {
        // 1.获取登录用户ID
        Long userId = getUserId();
        // 2.判断当前登录用户是否已经点赞
        String key = "article:liked:" + articleId;
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        if (ObjectUtil.isNull(score)) {
            // 3.如果未点赞,可以点赞
            // 3.1 数据库点赞数 + 1
            boolean isSuccess = articleService.update().setSql("liked = liked + 1").eq("id", articleId).update();
            // 3.2 保存用户到Redis的set集合
            if (isSuccess) {
                stringRedisTemplate.opsForZSet().add(key, userId.toString(), System.currentTimeMillis());
            }
        } else {
            // 4. 如果已经点赞,取消点赞
            // 4.1 数据库点赞数 - 1
            boolean isSuccess = articleService.update().setSql("liked = liked - 1").eq("id", articleId).update();
            // 4.2 把用户从Redis的set集合移除
            if (isSuccess) {
                stringRedisTemplate.opsForZSet().remove(key, userId.toString());
            }

        }

        return AjaxResult.success();
    }

    /**
     * @title: 文章点赞top5
     * @params: articleId 文章ID
     * @date: 2022/7/11 9:53
     */
    @GetMapping("/queryArticleLikes")
    public AjaxResult queryArticleLikes(Long articleId) {
        String key = "article:liked:" + articleId;
        // 1.查询top5点赞用户 SortedSet zRange key 0 4
        Set<String> top5 = stringRedisTemplate.opsForZSet().range(key, 0, 4);
        // 1.2判断点赞用户集合是否为空
        if (top5 == null || top5.isEmpty()) {
            return AjaxResult.success(Collections.emptyList());
        }
        // 2.解析其中用户ID
        List<Long> ids = top5.stream().map(Long::valueOf).collect(Collectors.toList());
        String idStr = StrUtil.join(",", ids);
        // 3.根据用户ID查询用户信息 WHERE id IN (5,1) ORDER BY FIELD(id,5,1)
        // 3.1 MySQL使用IN查询的时候怎么保证查询结果是根据我们传入的ids顺序排列,使用ORDER BY FIELD(id,ids)
        List<UserDTO> userDTOS = userService.query().in("id", ids).last("ORDER BY FIELD(id," + idStr + ")").list()
                .stream()
                .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
                .collect(Collectors.toList());

        return AjaxResult.success(userDTOS);
    }


}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值