热搜排序实现——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 getSkuHotSearch(Integer backwardDay, Integer hotNum) {

        Date nowDate = new Date();
        int end = hotNum * 3;
        List totalList = new ArrayList<>(backwardDay * end);
        for (int i = 0; i <= backwardDay; i++) {
            Set 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 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.comparingByValue().reversed()).forEachOrdered(e -> map.put(e.getKey(), e.getValue()));
        List respList = new ArrayList<>();
        map.entrySet().stream().limit(hotNum).forEach(entry -> {
            respList.add(entry.getKey());
        });
        return respList;
    }

}

你可能感兴趣的:(热搜排序实现——Redis有序集合zset)