热搜排序实现——Redis有序集合zset

这里主要涉及存储和查询方案。不涉及前端搜索的分词解析。完整方案,需要包括前端分词,排除停止词,挖掘相关的词后再进行热搜词的入库和搜索。

Redis Zincrby 命令对有序集合中指定成员的分数加上增量 increment
当 key 不存在,或分数不是 key 的成员时, ZINCRBY key increment member 等同于 ZADD key increment member 。

如:对key为2019-11-25,成员为keywords,增加5分

redis 127.0.0.1:6379> ZINCRBY '2019-11-25' 5 keywords

Redis Zrange 返回有序集中,结果由小到大;Zrevrange 命令返回结果由大到小。

如:查出key为2019-11-25,top3的成员

redis 127.0.0.1:6379> ZRANGE '2019-11-25'  0 3

利用有序集合zset的特性,即可达到按权重排序的效果。

Java实现:

@Component
@Slf4j
public class HotSearchProcessor {

    /**
     * 保存搜索
     * @param keyword
     */
    public void saveSkuSearch(String keyword){
            JedisUtil.getJedisInstance().execZIncrBy(DateUtil.format(new Date(), "yyyyMMdd"), 1, keyword);
    }
   
    /**
     * 获取热搜
     *
     * @param backwardDay 统计天数
     * @param hotNum      热门检索数量
     * @return
     */
    public List<String> getSkuHotSearch(Integer backwardDay, Integer hotNum) {

        Date nowDate = new Date();
        int end = hotNum * 3;
        List<MallSkuHotSearchResp> totalList = new ArrayList<>(backwardDay * end);
        for (int i = 0; i <= backwardDay; i++) {
            Set<Tuple> tupleSet = JedisUtil.getJedisInstance().execZrevrangeWithScores(DateUtil.format(DateUtils.addDays(nowDate, 0 - i), "yyyyMMdd"), 0, end);
            if (CollectionUtils.isNotEmpty(tupleSet)) {
                for (Tuple tuple : tupleSet) {
                    MallSkuHotSearchResp resp = new MallSkuHotSearchResp();
                    resp.setScore((int) tuple.getScore());
                    resp.setSearchKeyword(tuple.getElement());
                    totalList.add(resp);
                }
            }
        }
        Map<String, Integer> map = new LinkedHashMap<>(totalList.size());
        totalList.stream().collect(Collectors.groupingBy(MallSkuHotSearchResp::getSearchKeyword)).forEach((k, v) -> {
            map.put(k, v.stream().mapToInt(MallSkuHotSearchResp::getScore).sum());
        });
        map.entrySet().stream().sorted(Map.Entry.<String, Integer>comparingByValue().reversed()).forEachOrdered(e -> map.put(e.getKey(), e.getValue()));
        List<String> respList = new ArrayList<>();
        map.entrySet().stream().limit(hotNum).forEach(entry -> {
            respList.add(entry.getKey());
        });
        return respList;
    }

}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1 Redis介绍1.1 什么是NoSql为了解决高并发、高可扩展、高可用、大数据存储问题而产生的数据库解决方...
    克鲁德李阅读 5,371评论 0 36
  • 和Sets相比,SortedSets增加了一个权重参数score,使得集合中的元素能够按score进行有序排列, ...
    架构飞毛腿阅读 3,881评论 0 0
  • 有序集合 有序集合相对于哈希、列表、集合来说会有一点点陌生,但既然叫有序集合,那么它和集合必然有着联系,它保留了集...
    linuxzw阅读 1,047评论 0 5
  • // +-----------------------------------------------------...
    Robinbing阅读 1,457评论 0 0
  • Ubuntu下安装redis 安装redis 在 Ubuntu 系统安装 Redi 可以使用以下命令: 启动 Re...
    riverstation阅读 975评论 0 0