使用代码逻辑实现业务中的模糊查询

前言

实际工作中,与C端交互的需求常会涉及到模糊查询,解决思路一般有如下几种:

  1. 数据库实现:like语句,全文索引;
  2. ES实现;
  3. 代码逻辑实现;

三种解决方案在针对不同场景往往能得到很好的运行效果,本文主要介绍第三种。


一、适用场景

已有的功能上忽然要加一些筛选条件,并且还要求支持模糊查询,此时如果使用数据库必然要考虑在原有表设计上加一些索引,但如果使用like语法还不能有效利用到索引,这时就可以考虑在已查出的大范围数据下使用业务逻辑来进行筛选,可以想到的筛选方法有如下几种:

  • 条件字段拼接后使用indexOf()方法;
  • 条件字段拼接后使用contains()方法;
  • 使用List的contains()方法;
  • 使用Map的containsKey()方法;
    下面对四种方法一一就行实现和比较。

二、数据筛选

1.分析

四种实现方式,实现1与2可以进行模糊查询,其余两种只能进行精确匹配,用字符串实现最好使用一个分隔符进行隔开(当然最好使用一个特别的,保证不会与实际内容冲突的标识),隔开的目的是防止多个字符串拼接后得到本不应该存在的内容,如:用户查手机号为18899776600的内容,而作为筛选的字段分别有账号:2021070018899,昵称:776600CSDN,若不用分割,拼接后的内容为“2021070018899776600CSDN”,此时我们发现用户想要查找的内容出现在了拼接字符串中,所以字段分割是一定要做的。

2.实现

条件字段拼接后使用indexOf()方法:

long begin = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            StringBuilder queryStr = new StringBuilder();
            queryStr.append("测试人员");
            queryStr.append("-");
            queryStr.append("13680001111");
            queryStr.append("-");
            queryStr.append("1610413816458");
            queryStr.append("-");
            queryStr.append("1098713809878");
            int index = queryStr.indexOf("109871");
            queryStr.reverse();
        }
        System.out.println("用时:" + (System.currentTimeMillis() - begin));

条件字段拼接后使用contains()方法:

long begin1 = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            StringBuilder queryStr = new StringBuilder();
            queryStr.append("测试人员");
            queryStr.append("-");
            queryStr.append("13680001111");
            queryStr.append("-");
            queryStr.append("1610413816458");
            queryStr.append("-");
            queryStr.append("1098713809878");
            boolean result = queryStr.toString().contains("109871");
            queryStr.reverse();
        }
        System.out.println("用时:" + (System.currentTimeMillis() - begin1));

使用List的contains()方法:

long begin2 = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            StringBuilder queryStr = new StringBuilder();
            queryStr.append("测试人员");
            queryStr.append("-");
            queryStr.append("13680001111");
            queryStr.append("-");
            queryStr.append("1610413816458");
            queryStr.append("-");
            queryStr.append("1098713809878");
            String[] conditionArr = queryStr.toString().split("-");
            List<String> conditonList = Arrays.asList(conditionArr);
            boolean result = conditonList.contains("1098713809878");
            queryStr.reverse();
            conditonList = null;
            conditionArr = null;
        }
        System.out.println("用时:" + (System.currentTimeMillis() - begin2));

使用Map的containsKey()方法:

long begin3 = System.currentTimeMillis();
        Map<String, String> queryConditions = Maps.newHashMap();
        for (int i = 0; i < 10000; i++) {
            queryConditions.put("测试人员", "测试人员");
            queryConditions.put("13680001111", "13680001111");
            queryConditions.put("1610413816458", "1098713809878");
            queryConditions.put("1098713809878", "1098713809878");
            boolean result = queryConditions.containsKey("1098713809878");
            queryConditions.clear();
        }
        System.out.println("用时:" + (System.currentTimeMillis() - begin3));

3.对比

从表中不难发现,方法1和2的性能是差不多的,因为两种方法的底层实现其实是一致的,当筛选数据达到10万的时候,使用Map实现的方式性能优势开始显现,而到100万,性能远超其他方式,不过方法1和2仍然可以保持在500ms内,正常的业务场景也是可以接受的。

处理数量处理方式用时(ms)
100012
100022
100036
1000433
1000017
10000214
10000320
10000421
100000149
100000251
100000396
100000430
10000001368
10000002488
100000031073
10000004149

三、总结

总而言之,并不是只要涉及到数据查询我们就要考虑数据库或者其他存储工具,在恰当的时候合理的使用内存和数据结构,也可以很好地满足当下的业务需要。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值