Redis实现点赞

news2024/11/26 8:31:32
  部分实体类
@TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 商户id
     */
    private Long shopId;
    /**
     * 用户id
     */
    private Long userId;
    /**
     * 用户图标
     */
    @TableField(exist = false)
    private String icon;
    /**
     * 用户姓名
     */
    @TableField(exist = false)
    private String name;
    /**
     * 是否点赞过了
     */
    @TableField(exist = false)
    private Boolean isLike;
逻辑层代码 (没有实现排行榜时的代码.使用Set)
 //打开一个博客时调用该方法,可以进行是否高亮展示
    @Override
    public Result queryBlogById(Long id) {
        //查询blog
        Blog blog = getById(id);
        if(blog==null){
            return Result.fail("笔记不存在");
        }
        queryBlogUser(blog);
        //查询blog是否被点赞,返回给前端让前端进行判断是否高亮显示
        isBlogLiked(blog);
        return Result.ok(blog);
    }
    //给类中判断是否已经点赞的字段isLike赋值
    private void isBlogLiked(Blog blog) {
        //1.获取登录用户
        Long userId = UserHolder.getUser().getId();
        //2.判断当前登录用户是否已经点赞
        String key = "blog:liked" + blog.getId();
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
        blog.setIsLike(BooleanUtil.isTrue(isMember));
    }
    //通过另外一张表,给类中对应数据库表中不存在的两个字段赋值
    private void queryBlogUser(Blog blog) {
        //查询blog有关的用户
        Long userId = blog.getUserId();
        User user = userService.getById(userId);
        blog.setName(user.getNickName());
        blog.setIcon(user.getIcon());
    }

    //点击点赞按钮时,执行该方法,进行点赞与取消点赞
    @Override
    public Result likeBlog(Long id) {
        //1.获取登录用户
        Long userId = UserHolder.getUser().getId();
        //2.判断当前登录用户是否已经点赞
        String key = "blog:liked" + id;
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
        if(BooleanUtil.isFalse(isMember)){
            //3.如果未点赞,可以点赞
            //3.1 数据库点赞数加1
            boolean isSuccess = this.update().setSql("liked = liked + 1").eq("id", id).update();
            //3.2 保存用户到Redis的set集合
            if(isSuccess){
                stringRedisTemplate.opsForSet().add(key, userId.toString());
            }
        }else {
            //4.如果已点赞取消点赞
            //4.1数据库点赞数-1
            boolean isSuccess = this.update().setSql("liked = liked - 1").eq("id", id).update();
            //4.2 把用户从Redis的set集合中移除
            if(isSuccess){
                stringRedisTemplate.opsForSet().remove(key, userId.toString());
            }
        }

        return Result.ok();
    }
逻辑层代码(实现排行榜时的代码 ,使用了SortedSet)

 

    //打开一个博客时调用该方法,可以进行是否高亮展示
    @Override
    public Result queryBlogById(Long id) {
        //查询blog
        Blog blog = getById(id);
        if(blog==null){
            return Result.fail("笔记不存在");
        }
        queryBlogUser(blog);
        //查询blog是否被点赞,返回给前端让前端进行判断是否高亮显示
        isBlogLiked(blog);
        return Result.ok(blog);
    }
    //给类中判断是否已经点赞的字段isLike赋值
    private void isBlogLiked(Blog blog) {
        //1.获取登录用户
        UserDTO user = UserHolder.getUser();
        if(user==null){
            //用户未登录,无需查询是否点赞
            return;
        }
        Long userId = user.getId();
        //2.判断当前登录用户是否已经点赞
        String key = BLOG_LIKED_KEY + blog.getId();
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        blog.setIsLike(score != null);
    }
    //通过另外一张表,给类中对应数据库表中不存在的两个字段赋值
    private void queryBlogUser(Blog blog) {
        //查询blog有关的用户
        Long userId = blog.getUserId();
        User user = userService.getById(userId);
        blog.setName(user.getNickName());
        blog.setIcon(user.getIcon());
    }

    //点击点赞按钮时,执行该方法,进行点赞与取消点赞
    @Override
    public Result likeBlog(Long id) {
        //1.获取登录用户
        Long userId = UserHolder.getUser().getId();
        //2.判断当前登录用户是否已经点赞
        String key = BLOG_LIKED_KEY + id;
        //查询出的score为空,就为未点赞
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        if(score == null){
            //3.如果未点赞,可以点赞
            //3.1 数据库点赞数加1
            boolean isSuccess = this.update().setSql("liked = liked + 1").eq("id", id).update();
            //3.2 保存用户到Redis的SortedSet集合 zadd key value score
            if(isSuccess){
                stringRedisTemplate.opsForZSet().add(key, userId.toString(), System.currentTimeMillis());
            }
        }else {
            //4.如果已点赞取消点赞
            //4.1数据库点赞数-1
            boolean isSuccess = this.update().setSql("liked = liked - 1").eq("id", id).update();
            //4.2 把用户从Redis的set集合中移除
            if(isSuccess){
                stringRedisTemplate.opsForZSet().remove(key, userId.toString());
            }
        }

        return Result.ok();
    }

    @Override
    public Result queryBlogByLikes(Long id) {
        // 1.查询top5的点赞用户 zrange key 0 4
        String key = BLOG_LIKED_KEY + id;
        Set<String> top5 = stringRedisTemplate.opsForZSet().range(key, 0, 4);
        if(top5 == null || top5.isEmpty()){
            return Result.ok(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) 用于指定id先执行哪个
        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());
        //4.返回
        return Result.ok(userDTOS);
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2190309.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

lxml安装失败的一个解决方案

下载离线安装包&#xff0c;网址 https://pypi.org/simple/lxml/需要对应自己的python版本&#xff0c;网上教程很多&#xff0c;不再赘述 下载完成后将该文件&#xff0c;重命名&#xff08;下面是下载好的文件&#xff0c;上面是重命名的文件&#xff0c;就是在第二个版本&a…

【Linux】进程周边之优先级

目录 一、优先级 1.为什么要有进程优先级&#xff1f; 2.什么是进程优先级&#xff1f; 3.优先级的初始设定 3.1 PRI 和 NI 3.2如何修改优先级&#xff1f;&#xff08;sudo/root&#xff09; 3.2.1 概念&#xff1a; 3.2.2 如何查看进程的优先级&#xff1f; 3.3.3 或…

【深度学习】自动微分——Autodiff or Autograd?

论文 [1].CSC321 Lecture 10: Automatic Differentiation [2].Automatic Differentiation in Machine Learning:a Survey 关键点总结&#xff1a; 雅可比矩阵&#xff1a;对于多变量函数 y ⃗ f ( x ⃗ ) \vec{y} f(\vec{x}) y ​f(x )&#xff0c;其梯度矩阵&#xff08;…

GPT新功能Canvas!对普通用户最友好的功能!

原文链接&#xff1a;GPT4新功能Canvas!对普通用户最友好的功能&#xff01; ChatGPT更新了一个极度优雅&#xff0c;对普通人极度友好的功能。 而且&#xff0c;顺带&#xff0c;又碾死了一批AI赛道里&#xff0c;做AI文本编辑和Code Copilot的初创企业&#xff0c;一波端掉…

自动驾驶核心技术:感知融合、规划决策、控制执行

1、前言 简单来说&#xff0c;实现自动驾驶需要解决三个核心问题&#xff1a;“我在哪?我要去哪?我该如何去?”能完整解决这三个问题就是真正的自动驾驶。 目前&#xff0c;自动驾驶汽车关键技术主要包括环境感知、精准定位、决策与规划、控制与执行、高精地图与车联网V2X以…

ZYNQ:GPIO 之 MIO 按键中断实验

实验目的 使用底板上的 PS 端的用户按键 PS_KEY1 通过中断控制核心板上 LED2 的亮灭 简介 Zynq 芯片的 PS 部分是基于使用双核 Cortex-A9 处理器和 GIC pl390 中断控制器的 ARM 架构。中断结 构与 CPU 紧密链接&#xff0c;并接受来自 I/O 外设&#xff08;IOP&#xff09…

P4240 毒瘤之神的考验

毒瘤之神的考验 - 洛谷 定义 猜想与有关 发现上式1-1 上下两边乘gcd(i,j)有 带入1-1有 化简 n<m 经典代换Tke eT/k 然后化简不了了 这个时候我们可以把一部分看出一个整体 分析这两个函数&#xff0c;发现f(x) 可以在下预处理出来 g(x,y)有以下递推式 因此也可以在下处理…

三、流程控制

流程控制 选择结构&#xff08;if-else&#xff09;选择结构&#xff08;when&#xff09;循环结构&#xff08;for&#xff09;循环结构&#xff08;while&#xff09; 经过前面的学习&#xff0c;我们知道&#xff0c;程序都是从上往下依次运行的&#xff0c;但是&#xff0c…

事件抽取(Event Extraction, EE)

一、引言 事件抽取&#xff08;Event Extraction, EE&#xff09;是信息抽取领域中的一个重要任务&#xff0c;旨在从非结构化文本中识别和抽取事件相关的信息。事件抽取通常包括识别事件触发词、事件类型以及事件中的参与者、时间、地点等元素&#xff0c;最终将这些信息结构…

【进阶OpenCV】 (4)--图像拼接

文章目录 图像拼接1. 读取图片2. 计算图片特征点及描述符3. 建立暴力匹配器4. 特征匹配5. 透视变换6. 图像拼接 总结 图像拼接 图像拼接是一项将多张有重叠部分的图像&#xff08;这些图像可能是不同时间、不同视角或者不同传感器获得的&#xff09;拼成一幅无缝的全景图或高分…

论文翻译 | Model-tuning Via Prompts Makes NLP Models Adversarially Robust

摘要 近年来&#xff0c;NLP从业者集中于以下实践:(i)导入现成的预训练(掩码)语言模型;(ii)在CLS令牌的隐藏表示(随机初始化权重)上附加多层感知器;(iii)在下游任务(MLP-FT)上微调整个模型。这一过程在标准的NLP基准上产生了巨大的收益&#xff0c;但这些模型仍然很脆弱&#x…

mysql单表查询·3

准备好表 create table product(id int primary key,name varchar(32),price double,category varchar(32) ); # 插入数据 INSERT INTO product(id,name,price,category) VALUES(1,联想,5000,c001); INSERT INTO product(id,name,price,category) VALUES(2,海尔,3000,c001); I…

加密与安全_HOTP一次性密码生成算法

文章目录 HOTP 的基础原理HOTP 的工作流程HOTP 的应用场景HOTP 的安全性安全性增强措施Code生成HOTP可配置项校验HOTP可拓展功能计数器&#xff08;counter&#xff09;计数器在客户端和服务端的作用计数器的同步机制客户端和服务端中的计数器表现服务端如何处理计数器不同步计…

好用的苹果笔推荐!五大高品质王者款!附避坑宝典助你选购无忧!

现在平板和电容笔在一定程度上可以替代传统的笔和纸&#xff0c;很多用户在购置iPad后&#xff0c;急需找到一款好用的电容笔。但由于苹果原装笔的价格太过高昂&#xff0c;让许多人不得不选择平替电容笔&#xff01;下面我就为大家推荐五款高品质的电容笔&#xff0c;并分享几…

单细胞hdWGCNA分析学习和整理

hdWGCNA的分析逻辑是跟bulkRNA数据中的WGCNA基本一样&#xff0c;只是hdWGCNA中多了一步metacell过程&#xff0c;有助于减少无用的信息(单细胞数据有很多零值&#xff0c;会影响分析结果)。 WGCNA的基础信息可见既往推文: https://mp.weixin.qq.com/s/2Q37RcJ1pBy_WO1Es8upIg…

二分查找算法专题(2)

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; 优选算法专题 对于二分查找算法不是很了解或者只了解一部分的小伙伴一定要去看下面这篇博客&#xff1a;二分查找算法的介绍与另外一种查找方…

【EcoNAS: Finding Proxies for Economical Neural Architecture Search】读后感

鄙人近日阅读了来自 CVPR2020 的一篇论文, 在这里与大家分享一下读后感, 有些东西可能不一定正确, 还望大家指正. Exploration Study 进化算法是 NAS 中一种常用的搜索算法, 使用进化算法时, 如果将每一个候选网络训练到完全收敛来评估性能的话, 需要耗费大量的资源 (时间, G…

现代身份和访问管理 IAM 如何降低风险

您的公司是否仍在使用 1998 年时的身份管理系统&#xff1f;仅凭用户名和密码就能登录本地网络并访问几乎所有资源吗&#xff1f; 虽然大多数企业已经转向现代身份和访问管理(IAM) 平台&#xff0c;但成千上万的企业和其他组织仍然依赖过时的用户名/密码系统。 如果你看一下传…

Ubuntu18.04配置OpenPCDet并运行demo过程记录

一、概述 因为最近需要配置OpenPCDet&#xff0c;发现在配置过程中存在诸多的问题需要解决&#xff0c;将过程中所遇到的问题进行记录保存。 二、具体配置过程 &#xff08;一&#xff09;参考链接 因为中间遇到了很多问题&#xff0c;参考了很多不少相应的博客进行问题解决。…

【Unity】unity安卓打包参数(个人复习向/有不足之处欢迎指出/侵删)

1.Texture Compression 纹理压缩 设置发布后的纹理压缩格式 Use Player Settings:使用在播放器设置中设置的纹理压缩格式 ETC&#xff1a;使用ETC格式&#xff08;兼容&#xff09; ETC2&#xff1a;使用ETC2格式&#xff08;很多设备不支持&#xff09; ASTC&#xff1a;使用…