基于redis实现模糊匹配的简单热词推荐

场景

用户在输入时,往往需要根据输入内容匹配,按照热度排序推荐一些完整的内容,来减少用户输入,提升体验。我思考了一种少量数据的简单实现方式。使用redis的key来进行模糊匹配,然后根据热度进行排序输出;

实现思路

考虑热度是有时间效应,一个key,value不好办;然后想到了将时间和热度合并成一个,有了思路就可以考虑具体实现了。
将时间和热度转为int型,然后合并成一个long,就解决问题了。int最大值‭4294967295‬,热度达不到这么大,时间转换为例如:2022051217,以小时隔断,离最大值也差几千年,完全用不到这么久。完美解决。

先看看效果

redis中添加了如下数据

@Autowired
private RedissonClient redisson;

@PostConstruct
public void test() {
    redisson.getAtomicLong("java开发").set(0);
    redisson.getAtomicLong("javaScript").set(0);
    redisson.getAtomicLong("java培训").set(0);
    redisson.getAtomicLong("java面试题").set(0);
    redisson.getAtomicLong("java开发工具").set(0);
    redisson.getAtomicLong("java编程规范").set(0);
}

然后打开postMan或者ApiPost测试,输入”开发“
在这里插入图片描述
给”java开发“热度加1
在这里插入图片描述
再来输入”开发“看看效果
在这里插入图片描述
到这里就简单实现了这个功能,根据时间降低热度以后在做

接口代码

@RestController
@RequestMapping("/word")
public class WordTestController {

    @Autowired
    private RedissonClient redisson;

    @PostMapping("/matching")
    public List<WordEntity> matching(@RequestParam String text) {
        Iterator<String> keys = redisson.getKeys().getKeysByPattern("*" + text + "*").iterator();
        MutableList<WordEntity> result = Lists.mutable.of();
        while(keys.hasNext()) {
            String word = keys.next();
            result.add(new WordEntity(word, redisson.getAtomicLong(word).get()));
        }
        Collections.sort(result);
        return result;
    }

    @PostMapping("/addHot")
    public int addHot(@RequestParam String word) {
        int []hotAndTime = DataConversion.separateLong2int(redisson.getAtomicLong(word).get());
        long newHotAndTime = DataConversion.combineTimeAndHot(System.currentTimeMillis(), hotAndTime[1] + 1);
        redisson.getAtomicLong(word).set(newHotAndTime);
        return hotAndTime[1] + 1;
    }
}

实体类

public class WordEntity implements Comparable<WordEntity> {

    /**
     * 单词
     */
    private String name;

    /**
     * 热度
     */
    private int hot;

    /**
     * 最新更新时间
     */
    private int time;

    public WordEntity(String name, long hotAndTime) {
        this.name = name;
        setHotAndTime(hotAndTime);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getHot() {
        return hot;
    }

    public void setHot(int hot) {
        this.hot = hot;
    }

    public int getTime() {
        return time;
    }

    public void setTime(int time) {
        this.time = time;
    }

    public void setHotAndTime(long hotAndTime) {
        int data[] = DataConversion.separateLong2int(hotAndTime);
        this.hot = data[1];
        this.time = data[0];
    }

    @Override
    public int compareTo(WordEntity o) {
        Long t1 = DataConversion.combineIntToLong(this.time, this.hot);
        Long t2 = DataConversion.combineIntToLong(o.time, o.hot);
        return t2.compareTo(t1);
    }
}

数据合并代码

public class DataConversion {

    public static long combineTimeAndHot(long time, int hot) {
        return combineIntToLong(timeStampToInt(time), hot);
    }

    /**
     * 转为年月日时,例如:2022051216
     * @param timeStamp
     * @return
     */
    public static int timeStampToInt(long timeStamp) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timeStamp);
        StringBuilder builder = new StringBuilder();
        builder.append(calendar.get(Calendar.YEAR));
        int month = calendar.get(Calendar.MONTH) + 1;
        if(month < 10) {
            builder.append(0);
        }
        builder.append(month);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        if(day < 10) {
            builder.append(0);
        }
        builder.append(day);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        if(hour < 10) {
            builder.append(0);
        }
        builder.append(hour);
        return Integer.valueOf(builder.toString());
    }

    /**
     * 将两个int合并成一个long存储
     * @param low 低位
     * @param high 高位
     * @return
     */
    public static long combineIntToLong(int low, int high) {
        return (long) low | (long) high << 32;
    }

    /**
     * 将一个long存储的数据拆分成两个int,顺序按照合成顺序
     * @param val
     * @return
     */
    public static int[] separateLong2int(long val) {
        int[] ret = new int[2];
        ret[0] = (int) (0xFFFFFFFFl & val);
        ret[1] = (int) (val >> 32);
        return ret;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值