redis Autocomplete 做简单的“按键精灵”

redis Autocomplete 

  1. 面对 自动提示所需要阐述的问题:
    1. 需求:输入 abc    提示出 abc相关的数据?
    2. 采用数据库能否完成此项操作?
    3. 为什么要使用redis?
    4. redis 有几种实现方式? 分别是什么?
  2. 针对上面的问题做一一回答:

1)当我们访问一个网站,需要搜索的时候,打开搜索框后,假如 我们 输入:abc 该网站可能自动帮你补全一些信息,做个自动提示功能。

2)采用 数据库能否完成呢?  当然是可以的。

eg:需要 搜索 名称,代码,简称之类的。 通过 sql语句完成. 

           select * from tablename t where  t.name like "%abc%" or t.code like "%abc%"  ...

这种方式一定是可以的,只不过在时间上需要的时间长而已。 若我们做这种键盘精灵(快速提示相关内容),对时间要求肯定是比较高的,如果 项目小的话,可以考虑采用这种方式。

3)为什么采用redis?

redis也是一种存储结构。redis读取速度快,所以结合实际开发,做按键精灵在为合适不过了。

4)下面我们说说用redis 如何实现按键精灵。

假设内容是 a--z 之间的数据 ,输入 abc 能提示出  abbz  ---abcz 之间的数据。使用redis zset的存储结构能够完美的得到相应的结果。其中redis中提过了一个方法与其对应:zrangebylex  。   那我们要如何做呢?先把数据存储到redis中,使用zset 结构存储,其中score的值都为0.   (基于ASCII)

给定一些数据  abca abcd abcf abcu abau  abfh abac  .按照上述的搜索查找, 要想 输入abc ,会提示 abca,abcd,abcf,abcu.

 其中的核心代码:KCCompanyStockService.java

package com.vikedata.redissearch.service;

import com.alibaba.fastjson.JSON;
import com.vikedata.redissearch.dao.KCCompanyStockDAO;
import com.vikedata.redissearch.entity.KCCompanyStock;
import com.vikedata.redissearch.reids.JedisCache;
import com.vikedata.redissearch.utils.ChineseToUtfUtil;
import com.vikedata.redissearch.utils.MyPageInfo;
import com.vikedata.redissearch.utils.ResponseContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Auther: Zpjeck
 * @Date: 2019/10/16 18:06
 * @Description:
 */
@Service
public class KCCompanyStockService {

    @Autowired
    private JedisCache jedisCache;

    @Autowired
    private KCCompanyStockDAO kcCompanyStockDAO;

    private static Logger logger = LoggerFactory.getLogger(KCCompanyStockService.class);

    @Value("${spring.spirit.codeKey}")
    private String codeKey;
    @Value("${spring.spirit.pinyinKey}")
    private String pinyinKey;
    @Value("${spring.spirit.nameKey}")
    private String nameKey;
    @Value("${spring.spirit.all}")
    private String all;

    @Scheduled(cron = " 0 0 0 1/1 * ?  ")
    public void initData() {
        logger.info("键盘精灵开始更新数据。。。");
        List<KCCompanyStock> allCompanyStock = kcCompanyStockDAO.findAllCompanyStock();
        for (KCCompanyStock kcCompanyStock : allCompanyStock) {
            jedisCache.addZSet(codeKey, 0, kcCompanyStock.getSecuritycode());
            jedisCache.addZSet(pinyinKey, 0, kcCompanyStock.getSecuritypinyin());
            jedisCache.addZSet(nameKey, 0, ChineseToUtfUtil.convertStringToUTF8(kcCompanyStock.getSecurityshortname()));
            String key1 = all + "_" + kcCompanyStock.getSecuritycode();
            String key2 = all + "_" + kcCompanyStock.getSecuritypinyin();
            String key3 = all + "_" + ChineseToUtfUtil.convertStringToUTF8(kcCompanyStock.getSecurityshortname());
            jedisCache.setValue(key1, JSON.toJSONString(kcCompanyStock));
            jedisCache.setValue(key2, JSON.toJSONString(kcCompanyStock));
            jedisCache.setValue(key3, JSON.toJSONString(kcCompanyStock));
        }
        logger.info("键盘精灵更新数据 结束。。。");
    }

    public ResponseContext findByFont(Long pageNum, Long pageSize, String select) {
        pageNum = pageNum == null ? 1L : pageNum;
        pageSize = pageSize == null ? 100L : pageSize;
        select = select == null ? "" : select;
        select = select.toUpperCase();
        Set<String> zsetBylex = null;
        List<KCCompanyStock> list = new ArrayList<>();
        MyPageInfo<KCCompanyStock> pageInfo = new MyPageInfo<KCCompanyStock>();
        if (isInteger(select)) {
            // 全为数字
            String temp = "[" + select;
            zsetBylex = jedisCache.getZsetBylex(codeKey, temp, temp + ":");
            Set<String> zsetBylex1 = jedisCache.getZsetBylex(codeKey, temp, temp + ":", 0, pageSize.intValue());
            for (String s : zsetBylex1) {
                KCCompanyStock byParam = findByParam(s);
                if (byParam !=null){
                    if (byParam.getTrademarketcode().startsWith("069001001")){
                        byParam.setStockCode("sh"+byParam.getSecuritycode());
                    }
                    if (byParam.getTrademarketcode().startsWith("069001002")){
                        byParam.setStockCode("sz"+byParam.getSecuritycode());
                    }
                    list.add(byParam);
                }
            }
        }
        if (select.matches("[a-zA-Z]+")) {
            // 全都是英文字母
            String temp = "[" + select;
            zsetBylex = jedisCache.getZsetBylex(pinyinKey, temp, temp + "{");
            Set<String> zsetBylex1 = jedisCache.getZsetBylex(pinyinKey, temp, temp + "{", 0, pageSize.intValue());
            for (String s : zsetBylex1) {
                KCCompanyStock byParam = findByParam(s);
                if (byParam !=null){
                    if (byParam.getSecuritycode().startsWith("069001001")){
                        byParam.setStockCode("sh"+byParam.getSecuritycode());
                    }
                    if (byParam.getTrademarketcode().startsWith("069001002")){
                        byParam.setStockCode("sz"+byParam.getSecuritycode());
                    }
                    list.add(byParam);
                }
            }
        }
        if (isAllChinese(select)){
            String chinese = ChineseToUtfUtil.convertStringToUTF8(select);
            String temp = "[" + chinese ;
            zsetBylex = jedisCache.getZsetBylex(nameKey, temp, temp + "{");
            Set<String> zsetBylex1 = jedisCache.getZsetBylex(nameKey, temp, temp + "{", 0, pageSize.intValue());
            for (String s : zsetBylex1) {
                String string = ChineseToUtfUtil.convertUTF8ToString(s);
                KCCompanyStock byParam = findByParam(s);
                if (byParam !=null){

                    if (byParam.getSecuritycode().contains("A")){
                        byParam.setSecuritycode("");
                    }
                    if (byParam.getTrademarketcode().startsWith("069001001")){
                        byParam.setStockCode("sh"+byParam.getSecuritycode());
                    }
                    if (byParam.getTrademarketcode().startsWith("069001002")){
                        byParam.setStockCode("sz"+byParam.getSecuritycode());
                    }
                    list.add(byParam);
                }
            }
        }
        Long total = Long.valueOf(zsetBylex.size());
        long pages = (total - 1) / pageSize + 1;
        pageInfo.setPages(pages);
        pageInfo.setPageSize(Long.valueOf(list.size()));
        pageInfo.setTotal(total);
        pageInfo.setPageNum(pageNum);
        pageInfo.setList(list);
        return ResponseContext.getSuccess(pageInfo);
    }

    public KCCompanyStock findByParam(String param){
        if (param == null || "".equals(param)){
            return null;
        }
        String key = all + "_" + param;

        String value = jedisCache.getValue(key);
        KCCompanyStock kcCompanyStock = JSON.parseObject(value, KCCompanyStock.class);
        return kcCompanyStock;
    }


    public boolean isInteger(String str) {
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
        return pattern.matcher(str).matches();
    }

    // 判断是否为中文
    public static boolean isAllChinese(String str){
        for (int i = 0; i < str.length(); i++) {  //遍历所有字符
            char ch = str.charAt(i);
            if(ch < 0x4E00 ||ch > 0x9FA5){  //中文在unicode编码中所在的区间为0x4E00-0x9FA5
                return false;  //不在这个区间,说明不是中文字符,返回false
            }
        }

        return true;  //全部在中文区间,说明全部是中文字符,返回true
    }
    // 判断是否包含数字
    public static boolean HasDigit(String content) {
        boolean flag = false;
        if ("A".equals(content)){
            return true;
        }
        Pattern p = Pattern.compile(".*\\d+.*");
        Matcher m = p.matcher(content);
        if (m.matches()) {
            flag = true;
        }
        return flag;
    }





}

 目录结构:

 代码地址:

https://gitee.com/zpjeck/redis-Autocomplete

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值