SimSearch:一个轻量级的springboot项目索引构建工具,实现快速模糊搜索

简介

大部分项目都会涉及模糊搜索功能,而实现模糊搜索一般分为两个派系:

  • like简约派系
  • 搜索引擎派系

对于较为大型的项目来说,使用Solr、ES或者Milvus之类的引擎是比较流行的选择了(效果只能说优秀),而对于中小型项目,如果考虑这些较为重型的引擎,就意味着开发成本和运维成本

而一个简单的项目,特别是很多后台管理系统,模糊搜索仅仅是一个附带的功能(并非核心功能),所以我并不花太多时间去集成一个重量级的搜索引擎,此时为了方便就会选择like系列(偷懒的时候就这么干)

但是like也存在一些问题:

  • 数据量较大时,性能会急剧下降
  • 搜索词必须完整存在数据库中,只能进行左右模糊匹配
  • 如果使用左右两边模糊就会导致索引失效

终究是为一时的懒惰付出了代价…

但是…终究是想抽个空喝一口茶,顺便摸个鱼,如此我只能祭出SimSearch:一个轻量级的springboot项目索引构建工具,实现快速模糊搜索,相比于搜索引擎派系,这是一种轻量级的实现方式


索引测试

使用100万行中文 进行模糊搜索测试

i7 16g

存储模式(saver)平均耗时最大耗时最小耗时
nio-fs(nio文件模式)45.93ms144.5ms15.04ms
base-fs(常规文件系统)25.93ms97.32ms12.24ms
memory-fs(nmap文件模式)23.75ms114.12ms8.4ms
memory(内存模式)11.56ms42.35ms7.04ms

使用1000万行类似的中文创建索引后进行模糊搜索测试

存储模式(saver)平均耗时最大耗时最小耗时
nio-fs(nio文件模式)55.33ms151.5ms20.65ms
base-fs(常规文件系统)63.02ms102.73ms15.34ms
memory-fs(nmap文件模式)51.44ms180.38ms7.15ms
memory(内存模式)12.98ms50.26ms8.04ms

相对于文件系统,内存性能最好的无疑的,前提是内存有余,或者数据量不是很过分

测试的文本相对来说较短,如果是长文本,理论上上来说性能会下降一些

另外,以上结果仅仅作为一个参考


使用教程

可以有两种使用模式:注解和工具类,最完整的使用教程可以看源码的demo项目

先来说说注解使用,在原有的实体类和业务代码上标几个注解即可

1. 引入依赖

 <dependency>
    <groupId>cn.langpy</groupId>
    <artifactId>simsearch</artifactId>
    <version>2.0.0</version>
  </dependency>

使用了@Aspect注解,未引入的自行引入,如aspectj或者spring-boot-starter-aop

2. 配置信息

在application.properties中配置

#索引存储器 默认为内存 [memory,memory-fs,base-fs,nio-fs]
#内存富裕的情况下使用memory,如果是百万以上数据量选用fs系列
sim-search.saver=memory
#索引位置,saver!=memory时需配置
sim-search.dir=/data/indexlocation
#创建索引的核心线程数量,根据cpu自行决定,可不填,默认为5
sim-search.thread-core-size=5
#创建索引的最大线程数量,根据cpu自行决定,可不填,默认为200
sim-search.thread-max-size=10
#创建索引的线程队列容量,自行决定,可不填,默认为200000
sim-search.thread-queue-size=200000
#重启时是否要对之前的索引进行删除,默认为false
sim-search.index.init=true
#最大返回的搜索结果数量
sim-search.result.size=50

3. 在需要创建索引的实体上标注需要创建索引的字段

import cn.langpy.simsearch.annotation.IndexColumn;
import cn.langpy.simsearch.annotation.IndexId;

public class Student {
    /*索引唯一id 必须*/
    @IndexId 
    private String id;
    /*需要创建索引的字段:用来模糊搜索*/
    @IndexColumn
    private String studentName;
    @IndexColumn
    private String schoolName;
    private String age;
}

4. 在需要创建索引的方法上加上创建索引的注解

import cn.langpy.simsearch.annotation.CreateIndex;
import cn.langpy.simsearch.annotation.DeleteIndex;
import cn.langpy.simsearch.annotation.SearchIndex;

@Service
public class StudentServiceImpl implements StudentService {
    /*加上@CreateIndex后 异步创建索引,不影响正常业务的保存逻辑 indexParam:需要创建索引的参数*/
    /*该注解包含了更新操作 有则更新 无则创建*/
    @CreateIndex(indexParam = "student")
   public  boolean insert(Student student){
     /*业务逻辑*/
   }
}

5. 在需要删除索引的方法上加上删除索引的注解

@Service
public class StudentServiceImpl implements StudentService {
  /*加上@DeleteIndex后 异步删除索引,不影响正常业务的删除逻辑 indexParam:需要删除索引的参数*/
   @DeleteIndex(indexParam = "student")
   public  boolean delete(Student student){
     /*业务逻辑*/
   }
}

6. 搜索的时候自定义一个空的方法,加上注解即可

@Service
public class StudentServiceImpl implements StudentService {
   /*根据studentName属性搜索Student 搜索的属性要和实体的属性保持一致  */
   @SearchIndex(by = "studentName")
   public  List<Student> search(Student student){
    /*方法内部什么都不需要写*/
     return null;
   }

   /*根据schoolName属性搜索Student */
   @SearchIndex(by = "schoolName")
   public  List<Student> search(Student Student){
    /*方法内部什么都不需要写*/
    /*如果再索引中未查到对应信息,可通过该方法设置默认查询,比如往数据库进行like模糊匹配*/
     return searchWithLikeByName(schoolName);
   }
}

注意:搜索结果仅仅是搜索出加上@IndexId和@IndexColumn的字段,具体内容自行往业务数据库查询


使工具类使用

public class IndexManager{
    /*创建索引*/
    public static void createIndex(IndexContent indexContent);
    /*删除索引*/
    public static void deleteIndex(String idName, String idValue,Class entityClass);
    /*搜索 详见源码的demo项目*/
    public static <T> List<T> searchIndexIds(String name, String value,Class<?> entityClass);
    /*搜索 详见源码的demo项目*/
    public static <T> List<T> searchIndexObjects(String name, String value,Class entityClass);
    public static void deleteAll();
    /*为对象创建索引*/
    public static void createIndex(Object entity);
    public static void createIndexs(List<Object> entities);
}

源码

有用的话可以Star支持一下,让作者增强信心,好好维护和升级

Gitee

很简单的demo项目

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大Huoyo

提醒博主一下,该起来写文章了

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值