亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Redis筆記點(diǎn)贊排行榜的實(shí)現(xiàn)示例

 更新時(shí)間:2023年01月29日 15:50:02   作者:卒獲有所聞  
探店筆記類似點(diǎn)評(píng)網(wǎng)站的評(píng)價(jià),本文主要介紹了Redis筆記點(diǎn)贊排行榜的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

一、發(fā)布探店筆記

探店筆記類似點(diǎn)評(píng)網(wǎng)站的評(píng)價(jià),往往是圖文結(jié)合。對(duì)應(yīng)的表有兩個(gè)

  • 探店筆記表(主鍵、商戶id、用戶id、標(biāo)題、文字、圖片、探店文字描述、點(diǎn)贊數(shù)量、評(píng)論數(shù)量)
  • 評(píng)價(jià)表(筆記的評(píng)價(jià))

 先上傳圖片請(qǐng)求一次保存圖片接口,再點(diǎn)發(fā)布請(qǐng)求發(fā)布接口。這兩個(gè)接口已經(jīng)寫好

二、實(shí)現(xiàn)查看筆記接口

BlogController

@RestController
@RequestMapping("/blog")
public class BlogController {
 
    @Resource
    private IBlogService blogService;
   
    @GetMapping("/hot")
    public Result queryHotBlog(@RequestParam(value = "current", defaultValue = "1") Integer current) {
 
        return blogService.queryHotBlog(current);
    }
 
    @GetMapping("/{id}")
    public Result queryBlogById(@PathVariable("id") String id){
        return blogService.queryBlogById(id);
    }
}

IBlogService

public interface IBlogService extends IService<Blog> {
 
    Result queryBlogById(String id);
 
    Result queryHotBlog(Integer current);
}

BlogServiceImpl

@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {
 
    @Autowired
    private IUserService userService;
 
    @Override
    public Result queryHotBlog(Integer current) {
        // 根據(jù)用戶查詢
        Page<Blog> page = query()
                .orderByDesc("liked")
                .page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
        // 獲取當(dāng)前頁(yè)數(shù)據(jù)
        List<Blog> records = page.getRecords();
        // 查詢用戶
        records.forEach(this::queryBlogUser);
        return Result.ok(records);
    }
 
    private void queryBlogUser(Blog blog) {
        Long userId = blog.getUserId();
        User user = userService.getById(userId);
        blog.setName(user.getNickName());
        blog.setIcon(user.getIcon());
    }
 
    @Override
    public Result queryBlogById(String id) {
        Blog blog = getById(id);
        
        if(blog == null){
            return Result.fail("筆記不存在!");
        }
 
        queryBlogUser(blog);
 
        return Result.ok(blog);
    }
}

三、點(diǎn)贊功能

現(xiàn)在已經(jīng)寫好的點(diǎn)贊接口

問(wèn)題:這樣寫接口,可以一直按點(diǎn)贊重復(fù)點(diǎn)贊

需求

  • 同一個(gè)用戶只能點(diǎn)贊一次,再次點(diǎn)贊則取消點(diǎn)贊
  • 如果當(dāng)前用戶已經(jīng)點(diǎn)贊,則點(diǎn)贊按鈕高亮顯(前端已經(jīng)實(shí)現(xiàn),判斷blog類的isLike屬性)

實(shí)現(xiàn)步驟

  • 給Blog類中添加一個(gè)isLike字段,表示是否被當(dāng)前用戶點(diǎn)贊
  • 修改點(diǎn)贊功能,利用redis的set集合判斷用戶是否贊過(guò),未贊則點(diǎn)贊數(shù)+1,贊過(guò)則-1
  • 修改根據(jù)id查詢blog的業(yè)務(wù),判斷當(dāng)前用戶是否點(diǎn)贊過(guò),賦值給isLike字段
  • 修改分頁(yè)查詢blog業(yè)務(wù),判斷當(dāng)前用戶是否贊過(guò),賦值isLike字段

業(yè)務(wù)實(shí)現(xiàn)

@RestController
@RequestMapping("/blog")
public class BlogController {
 
    @Resource
    private IBlogService blogService;
 
    @PutMapping("/like/{id}")
    public Result likeBlog(@PathVariable("id") Long id) {
        return blogService.likeBlog(id);
    }
 
    @GetMapping("/hot")
    public Result queryHotBlog(@RequestParam(value = "current", defaultValue = "1") Integer current) {
        return blogService.queryHotBlog(current);
    }
 
    @GetMapping("/{id}")
    public Result queryBlogById(@PathVariable("id") String id){
        return blogService.queryBlogById(id);
    }
}

編寫完點(diǎn)贊操作的接口后還要修改之前的查詢接口,增加查詢是否已經(jīng)點(diǎn)贊 

@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {
 
    @Autowired
    private IUserService userService;
 
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
 
    @Override
    public Result queryHotBlog(Integer current) {
        // 根據(jù)用戶查詢
        Page<Blog> page = query()
                .orderByDesc("liked")
                .page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
        // 獲取當(dāng)前頁(yè)數(shù)據(jù)
        List<Blog> records = page.getRecords();
        // 查詢用戶
        records.forEach(blog -> {
            this.queryBlogUser(blog);
            this.isBlogLiked(blog);
        });
        return Result.ok(records);
    }
 
    @Override
    public Result likeBlog(Long id) {
        // 1、獲取登錄用戶
        UserDTO user = UserHolder.getUser();
        // 2、判斷當(dāng)前登錄用戶是否已經(jīng)點(diǎn)贊
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString());
        if(BooleanUtil.isFalse(isMember)) {
            // 3、如果未點(diǎn)贊,可以點(diǎn)贊
            // 3.1、數(shù)據(jù)庫(kù)點(diǎn)贊數(shù) +1
            boolean isSuccess = update().setSql("liked = liked+1").eq("id", id).update();
            // 3.2、保存用戶到 Redis 的 set 集合
            if(isSuccess){
                stringRedisTemplate.opsForSet().add(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString());
            }
        } else {
            // 4、如果已點(diǎn)贊,取消點(diǎn)贊
            // 4.1、數(shù)據(jù)庫(kù)點(diǎn)贊數(shù) -1
            boolean isSuccess = update().setSql("liked = liked - 1").eq("id", id).update();
            // 4.2、把用戶從 Redis 的 set 集合移除
            if(isSuccess){
                stringRedisTemplate.opsForSet().remove(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString());
            }
        }
        return Result.ok();
    }
 
 
    private void queryBlogUser(Blog blog) {
        Long userId = blog.getUserId();
        User user = userService.getById(userId);
        blog.setName(user.getNickName());
        blog.setIcon(user.getIcon());
    }
 
    @Override
    public Result queryBlogById(String id) {
        Blog blog = getById(id);
        
        if(blog == null){
            return Result.fail("筆記不存在!");
        }
 
        queryBlogUser(blog);
        // 查詢 Blog 是否被點(diǎn)贊
        isBlogLiked(blog);
 
        return Result.ok(blog);
    }
 
    private void isBlogLiked(Blog blog) {
        Long userId = blog.getUserId();
        String key = RedisConstants.BLOG_LIKED_KEY + blog.getId();
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
        blog.setIsLike(BooleanUtil.isTrue(isMember));
    }
}

四、點(diǎn)贊排行榜 

查出給這個(gè)筆記點(diǎn)贊的人,類似微信朋友圈的點(diǎn)贊,可以展示誰(shuí)點(diǎn)贊了,而且我們要進(jìn)行排序

所以我們得用SortedSet這種數(shù)據(jù)類型

1、修改點(diǎn)贊邏輯

把原本存入set改為存入zset多加個(gè)分?jǐn)?shù),分?jǐn)?shù)就是時(shí)間戳

@Override
    public Result likeBlog(Long id) {
        // 1、獲取登錄用戶
        UserDTO user = UserHolder.getUser();
        // 2、判斷當(dāng)前登錄用戶是否已經(jīng)點(diǎn)贊
        Double score = stringRedisTemplate.opsForZSet().score(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString());
        if(score == null) {
            // 3、如果未點(diǎn)贊,可以點(diǎn)贊
            // 3.1、數(shù)據(jù)庫(kù)點(diǎn)贊數(shù) +1
            boolean isSuccess = update().setSql("liked = liked+1").eq("id", id).update();
            // 3.2、保存用戶到 Redis 的 set 集合
            if(isSuccess){
                // 時(shí)間作為 key 的 score
                stringRedisTemplate.opsForZSet().add(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString(), System.currentTimeMillis());
            }
        } else {
            // 4、如果已點(diǎn)贊,取消點(diǎn)贊
            // 4.1、數(shù)據(jù)庫(kù)點(diǎn)贊數(shù) -1
            boolean isSuccess = update().setSql("liked = liked - 1").eq("id", id).update();
            // 4.2、把用戶從 Redis 的 set 集合移除
            if(isSuccess){
                stringRedisTemplate.opsForZSet().remove(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString());
            }
        }
        return Result.ok();
    }

然后是否被點(diǎn)贊的方法也要修改,根據(jù)key取出分?jǐn)?shù),分?jǐn)?shù)不為null就是點(diǎn)贊過(guò)了

 private void isBlogLiked(Blog blog) {
        UserDTO user = UserHolder.getUser();
        if(user == null){
            return;
        }
        Long userId = user.getId();
        String key = RedisConstants.BLOG_LIKED_KEY + blog.getId();
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        blog.setIsLike(score != null);
    }

2、點(diǎn)贊排行榜功能

需求:實(shí)現(xiàn)前五個(gè)點(diǎn)贊的用戶返回

我們先用動(dòng)態(tài)id去redis中查詢出前五個(gè)點(diǎn)贊用戶的id

然后根據(jù)id去數(shù)據(jù)庫(kù)中查詢信息封裝到dto再返回

    @GetMapping("/likes/{id}")
    public Result queryBlogLikes(@PathVariable("id") String id) {
        return blogService.queryBlogLikes(id);
    }
    @Override
    public Result queryBlogLikes(String id) {
        String key = RedisConstants.BLOG_LIKED_KEY + id;
        // 查詢 top5 的點(diǎn)贊用戶
        Set<String> top5 = stringRedisTemplate.opsForZSet().range(key, 0, 4);
        if(top5 == null){
            return Result.ok(Collections.emptyList());
        }
        // 解析出其中的用戶id
        List<Long> ids = top5.stream().map(Long::valueOf).collect(Collectors.toList());
        String join = StrUtil.join(",", ids);
        // 根據(jù)用戶id查詢用戶
        List<UserDTO> userDTOS = userService.query().in("id", ids).last("order by filed(id, "+join+")").list()
                .stream()
                .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
                .collect(Collectors.toList());
 
        return Result.ok(userDTOS);
    }

注意:如果我們mp直接用in來(lái)查詢根本不能保證點(diǎn)贊的順序,因?yàn)閕n查詢出來(lái)的是按照id順序返回的,沒(méi)有排序,我們要按照查詢id的順序來(lái)查,order by field(id,5,1)這樣

到此這篇關(guān)于Redis筆記點(diǎn)贊排行榜的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Redis筆記點(diǎn)贊內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • redis配置文件redis.conf中文版(基于2.4)

    redis配置文件redis.conf中文版(基于2.4)

    這篇文章主要介紹了redis配置文件redis.conf中文版(基于2.4),對(duì)英文不好的朋友是非常好的參考,需要的朋友可以參考下
    2014-06-06
  • Redis處理高并發(fā)之布隆過(guò)濾器詳解

    Redis處理高并發(fā)之布隆過(guò)濾器詳解

    這篇文章主要為大家介紹了Redis處理高并發(fā)之布隆過(guò)濾器詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • 基于redis實(shí)現(xiàn)世界杯排行榜功能項(xiàng)目實(shí)戰(zhàn)

    基于redis實(shí)現(xiàn)世界杯排行榜功能項(xiàng)目實(shí)戰(zhàn)

    前段時(shí)間,做了一個(gè)世界杯競(jìng)猜積分排行榜。對(duì)世界杯64場(chǎng)球賽勝負(fù)平進(jìn)行猜測(cè),猜對(duì)+1分,錯(cuò)誤+0分,一人一場(chǎng)只能猜一次。下面通過(guò)本文給大家分享基于redis實(shí)現(xiàn)世界杯排行榜功能項(xiàng)目實(shí)戰(zhàn),感興趣的朋友一起看看吧
    2018-10-10
  • redis的2種持久化方案深入講解

    redis的2種持久化方案深入講解

    這篇文章主要給大家介紹了關(guān)于redis的2種持久化方案的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用redis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • 利用Redis實(shí)現(xiàn)訪問(wèn)次數(shù)限流的方法詳解

    利用Redis實(shí)現(xiàn)訪問(wèn)次數(shù)限流的方法詳解

    這篇文章主要給大家介紹了關(guān)于如何利用Redis實(shí)現(xiàn)訪問(wèn)次數(shù)限流的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-02-02
  • 詳解Redis單線程架構(gòu)的優(yōu)勢(shì)與不足

    詳解Redis單線程架構(gòu)的優(yōu)勢(shì)與不足

    很多人都遇到過(guò)這么一道面試題:Redis是單線程還是多線程?這個(gè)問(wèn)題既簡(jiǎn)單又復(fù)雜,說(shuō)他簡(jiǎn)單是因?yàn)榇蠖鄶?shù)人都知道Redis是單線程,說(shuō)復(fù)雜是因?yàn)檫@個(gè)答案其實(shí)并不準(zhǔn)確,本文就給大家講講Redis單線程架構(gòu)的優(yōu)勢(shì)與不足,需要的朋友可以參考下
    2024-02-02
  • 使用Jedis面臨的非線程安全問(wèn)題詳解

    使用Jedis面臨的非線程安全問(wèn)題詳解

    網(wǎng)上都說(shuō)jedis實(shí)例是非線程安全的,常常通過(guò)JedisPool連接池去管理實(shí)例,在多線程情況下讓每個(gè)線程有自己獨(dú)立的jedis實(shí)例,但都沒(méi)有具體說(shuō)明為啥jedis實(shí)例時(shí)非線程安全的,本文就來(lái)和大家詳細(xì)說(shuō)說(shuō)
    2022-12-12
  • 詳解Redis實(shí)現(xiàn)限流的三種方式

    詳解Redis實(shí)現(xiàn)限流的三種方式

    這篇文章主要介紹了詳解Redis實(shí)現(xiàn)限流的三種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Redis列表類型的常用命令小結(jié)

    Redis列表類型的常用命令小結(jié)

    這篇文章給大家整理了在操作Redis列表類型中的常用命令,文章總結(jié)的很全面,對(duì)大家學(xué)習(xí)Redis具有一定的參考借鑒價(jià)值,下面來(lái)一起看看吧。
    2016-09-09
  • Windows下Redis?x64的安裝與使用教程詳解

    Windows下Redis?x64的安裝與使用教程詳解

    Redis是一款內(nèi)存高速緩存數(shù)據(jù)庫(kù),可以滿足我們對(duì)海量數(shù)據(jù)的讀寫需求,本文重點(diǎn)給大家介紹Windows下Redis?x64的安裝與使用教程,感興趣的朋友一起看看吧
    2022-03-03

最新評(píng)論