项目场景:
最近在做一个发布文章的小demo,根据文章点击次数,统计前十热门文章排行列表。
实现方案
采用redis 的 Zset数据类型,每次点击文章时,将文章id对应的分数字段+1,最后根据分数从高到底的顺序,取出前十个元素。
redisTemplate.opsForZSet().incrementScore("article", id, 1);
因为缓存中存储的是文章id,所以还需要根据id去数据库中查询对应的文章详情列表。
@Override
public List<Article> listHotTop() {
Set<Object> articles = redisTemplate.opsForZSet().reverseRange("article", 0, 9);
List<Integer> ids = articles.stream().map(s -> (int) s).collect(Collectors.toList());
LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(Article::getId, ids).select(Article::getId, Article::getTitle)
.last(" order by field(id," + StringUtils.join(ids, ",") + ")");
return baseMapper.selectList(queryWrapper);
}
问题描述:
最后的结果虽然取出了排名前十的文章列表,但是mysql 并不会按照我们传入的id顺序返回结果,甚至每次返回的顺序都不一样,自然也不是我们预想的按照点击量排名。
解决方案:
mysql 根据传入的字段列表进行排序,这里是需要根据传入的文章id排序,
基本语法:
select id, title from t_article order by field(id,1,3...)
注:如果是mybatis或者mybatis-plus,则需要手动在xml中编写sql或者在代码中拼接。
最后得到我们想要的结果。
实现效果: