簡(jiǎn)介
大部分項(xiàng)目都會(huì)涉及模糊搜索功能,而實(shí)現(xiàn)模糊搜索一般分為兩個(gè)派系:
- like簡(jiǎn)約派系
- 搜索引擎派系
對(duì)于較為大型的項(xiàng)目來(lái)說(shuō),使用Solr、ES或者M(jìn)ilvus之類的引擎是比較流行的選擇了(效果只能說(shuō)優(yōu)秀),而對(duì)于中小型項(xiàng)目,如果考慮這些較為重型的引擎,就意味著開(kāi)發(fā)成本和運(yùn)維成本
而一個(gè)簡(jiǎn)單的項(xiàng)目,特別是很多后臺(tái)管理系統(tǒng),模糊搜索僅僅是一個(gè)附帶的功能(并非核心功能),所以我并不花太多時(shí)間去集成一個(gè)重量級(jí)的搜索引擎,此時(shí)為了方便就會(huì)選擇like系列(偷懶的時(shí)候就這么干)
但是like也存在一些問(wèn)題:
- 數(shù)據(jù)量較大時(shí),性能會(huì)急劇下降
- 搜索詞必須完整存在數(shù)據(jù)庫(kù)中,只能進(jìn)行左右模糊匹配
- 如果使用左右兩邊模糊就會(huì)導(dǎo)致索引失效
終究是為一時(shí)的懶惰付出了代價(jià)…
但是…終究是想抽個(gè)空喝一口茶,順便摸個(gè)魚(yú),如此我只能祭出SimSearch:一個(gè)輕量級(jí)的springboot項(xiàng)目索引構(gòu)建工具,實(shí)現(xiàn)快速模糊搜索,相比于搜索引擎派系,這是一種輕量級(jí)的實(shí)現(xiàn)方式
索引測(cè)試
使用100萬(wàn)行中文 進(jìn)行模糊搜索測(cè)試
i7 16g
存儲(chǔ)模式(saver) | 平均耗時(shí) | 最大耗時(shí) | 最小耗時(shí) |
---|---|---|---|
nio-fs(nio文件模式) | 45.93ms | 144.5ms | 15.04ms |
base-fs(常規(guī)文件系統(tǒng)) | 25.93ms | 97.32ms | 12.24ms |
memory-fs(nmap文件模式) | 23.75ms | 114.12ms | 8.4ms |
memory(內(nèi)存模式) | 11.56ms | 42.35ms | 7.04ms |
使用1000萬(wàn)行類似的中文創(chuàng)建索引后進(jìn)行模糊搜索測(cè)試
存儲(chǔ)模式(saver) | 平均耗時(shí) | 最大耗時(shí) | 最小耗時(shí) |
---|---|---|---|
nio-fs(nio文件模式) | 55.33ms | 151.5ms | 20.65ms |
base-fs(常規(guī)文件系統(tǒng)) | 63.02ms | 102.73ms | 15.34ms |
memory-fs(nmap文件模式) | 51.44ms | 180.38ms | 7.15ms |
memory(內(nèi)存模式) | 12.98ms | 50.26ms | 8.04ms |
相對(duì)于文件系統(tǒng),內(nèi)存性能最好的無(wú)疑的,前提是內(nèi)存有余,或者數(shù)據(jù)量不是很過(guò)分
測(cè)試的文本相對(duì)來(lái)說(shuō)較短,如果是長(zhǎng)文本,理論上上來(lái)說(shuō)性能會(huì)下降一些
另外,以上結(jié)果僅僅作為一個(gè)參考
使用教程
可以有兩種使用模式:注解和工具類,最完整的使用教程可以看源碼的demo項(xiàng)目
先來(lái)說(shuō)說(shuō)注解使用,在原有的實(shí)體類和業(yè)務(wù)代碼上標(biāo)幾個(gè)注解即可
1. 引入依賴
<dependency>
<groupId>cn.langpy</groupId>
<artifactId>simsearch</artifactId>
<version>2.0.0</version>
</dependency>
使用了@Aspect注解,未引入的自行引入,如aspectj或者spring-boot-starter-aop
2. 配置信息
在application.properties中配置
#索引存儲(chǔ)器 默認(rèn)為內(nèi)存 [memory,memory-fs,base-fs,nio-fs]
#內(nèi)存富裕的情況下使用memory,如果是百萬(wàn)以上數(shù)據(jù)量選用fs系列
sim-search.saver=memory
#索引位置,saver!=memory時(shí)需配置
sim-search.dir=/data/indexlocation
#創(chuàng)建索引的核心線程數(shù)量,根據(jù)cpu自行決定,可不填,默認(rèn)為5
sim-search.thread-core-size=5
#創(chuàng)建索引的最大線程數(shù)量,根據(jù)cpu自行決定,可不填,默認(rèn)為200
sim-search.thread-max-size=10
#創(chuàng)建索引的線程隊(duì)列容量,自行決定,可不填,默認(rèn)為200000
sim-search.thread-queue-size=200000
#重啟時(shí)是否要對(duì)之前的索引進(jìn)行刪除,默認(rèn)為false
sim-search.index.init=true
#最大返回的搜索結(jié)果數(shù)量
sim-search.result.size=50
3. 在需要?jiǎng)?chuàng)建索引的實(shí)體上標(biāo)注需要?jiǎng)?chuàng)建索引的字段
import cn.langpy.simsearch.annotation.IndexColumn;
import cn.langpy.simsearch.annotation.IndexId;
public class Student {
/*索引唯一id 必須*/
@IndexId
private String id;
/*需要?jiǎng)?chuàng)建索引的字段:用來(lái)模糊搜索*/
@IndexColumn
private String studentName;
@IndexColumn
private String schoolName;
private String age;
}
4. 在需要?jiǎng)?chuàng)建索引的方法上加上創(chuàng)建索引的注解
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后 異步創(chuàng)建索引,不影響正常業(yè)務(wù)的保存邏輯 indexParam:需要?jiǎng)?chuàng)建索引的參數(shù)*/
/*該注解包含了更新操作 有則更新 無(wú)則創(chuàng)建*/
@CreateIndex(indexParam = "student")
public boolean insert(Student student){
/*業(yè)務(wù)邏輯*/
}
}
5. 在需要?jiǎng)h除索引的方法上加上刪除索引的注解
@Service
public class StudentServiceImpl implements StudentService {
/*加上@DeleteIndex后 異步刪除索引,不影響正常業(yè)務(wù)的刪除邏輯 indexParam:需要?jiǎng)h除索引的參數(shù)*/
@DeleteIndex(indexParam = "student")
public boolean delete(Student student){
/*業(yè)務(wù)邏輯*/
}
}
6. 搜索的時(shí)候自定義一個(gè)空的方法,加上注解即可
@Service
public class StudentServiceImpl implements StudentService {
/*根據(jù)studentName屬性搜索Student 搜索的屬性要和實(shí)體的屬性保持一致 */
@SearchIndex(by = "studentName")
public List<Student> search(Student student){
/*方法內(nèi)部什么都不需要寫(xiě)*/
return null;
}
/*根據(jù)schoolName屬性搜索Student */
@SearchIndex(by = "schoolName")
public List<Student> search(Student Student){
/*方法內(nèi)部什么都不需要寫(xiě)*/
/*如果再索引中未查到對(duì)應(yīng)信息,可通過(guò)該方法設(shè)置默認(rèn)查詢,比如往數(shù)據(jù)庫(kù)進(jìn)行l(wèi)ike模糊匹配*/
return searchWithLikeByName(schoolName);
}
}
注意:搜索結(jié)果僅僅是搜索出加上@IndexId和@IndexColumn的字段,具體內(nèi)容自行往業(yè)務(wù)數(shù)據(jù)庫(kù)查詢
使工具類使用
public class IndexManager{
/*創(chuàng)建索引*/
public static void createIndex(IndexContent indexContent);
/*刪除索引*/
public static void deleteIndex(String idName, String idValue,Class entityClass);
/*搜索 詳見(jiàn)源碼的demo項(xiàng)目*/
public static <T> List<T> searchIndexIds(String name, String value,Class<?> entityClass);
/*搜索 詳見(jiàn)源碼的demo項(xiàng)目*/
public static <T> List<T> searchIndexObjects(String name, String value,Class entityClass);
public static void deleteAll();
/*為對(duì)象創(chuàng)建索引*/
public static void createIndex(Object entity);
public static void createIndexs(List<Object> entities);
}
源碼
有用的話可以Star支持一下,讓作者增強(qiáng)信心,好好維護(hù)和升級(jí)
Gitee文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-430645.html
很簡(jiǎn)單的demo項(xiàng)目文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-430645.html
到了這里,關(guān)于SimSearch:一個(gè)輕量級(jí)的springboot項(xiàng)目索引構(gòu)建工具,實(shí)現(xiàn)快速模糊搜索的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!