全文检索Elasticserarch
前言:本文基于若依前后端分离版本(Spring Boot 3.3.0 + Vue 3 + Activiti 8.1.0)进行改造,相关教程可以在网上找到。在撰写此博客期间,笔者刚刚开始接触 Java Web,本系列下的文章内容包含大量“个人初期”视角,注意鉴别。
全文检索
回想一下我们查找知网的时候,我们可以搜索标题得知一些信息,同样,我们有的时候需要检索他的摘要才能得到一些算法和方法的信息。
所以,这个时候单纯去模糊查找MySQL数据库就不太合适了,我们需要一个新的数据库,他能保存文件的一些关键信息,包括{标题、作者、摘要(甚至是全文)}等,相比MySQL的一条条轻量化的记录数据(比如文档实际的保存位置、标题、ISBN等),我们期望新的数据库能将文本的全文进行保存,能让我们:翻开书看,查找书中内容。而不是只看封面获得一些“表面信息”。
这个时候就可以使用Elasticserarch:分布式搜索和分析引擎
对比一下MySQL?
MySQL的过程:建数据库,sql建表,Java中定义某个domain/calss,使用mapper映射实现增删查改。
- 比如:课程表、课程类、课程mapper、课程服务。
Elasticsearch过程:Java中定义某个domain/class,调用库函数保存和查找。
- 比如:文档类、文档保存与检索。
Elasticsearch基本结构以及处理对象基本结构(现阶段理解不一定对):
所以MySQL查,查一条条数据,去检索的是每一列、每一行,找到匹配的;Elasticserarch查,可以也是查每一个记录的属性,只不过这个属性中有一个巨无霸:content。他甚至可以是全文。
如果有一个人的名字,同时出现在多个文档中(内容层面),MySQL可查不到这些数据,Elasticserarch就可以查这些文档的内容,返回所有包含这个名字的文档。
MySQL: 数据库 -> 数据表(XX表)-> 主键+属性(保存位置、所属部门、创建者)
Elasticsearch: 数据库 -> 仓库(indexName)-> ID+其他文档内容(标题+作者+内容+介绍)
Elasticsearch中主要保存能用于检索的信息,MySQL记录更加详细的标签类的信息,二者可以通过某个属性连接。
如何使用?
定义实体类与仓库
我们在原有的MySQL的类上,新建一个类,它用来保存/承接Elasticsearch的搜索结果,需要注意的应该就是@Document注解。其他部分就像MySQL一样。
1 | import org.springframework.data.elasticsearch.annotations.Document; |
- 1、indexName:我们没有显式指明一个数据库,与MySQL似乎不太像,不过可以把这个indexName作为一个假想的数据库,我们在这个数据库下,只能查找ElasticsearchArchive这个类型。
- 2、 Elasticsearch也是要一个主键ID的,string类型,不过不同自己去设置,他会帮你自动生成的。别忘了@Id注解。
- 3、其他属性使用@Field,并标Type。
插入数据库
再插入数据库时,应该同时插入MySQL与Elasticsearch。
原本插入Archive数据库的方法,仅修改MySQL。
1 |
|
修改后:
1 |
|
MySQL由于可以使用mapper服务接口,可以避免直接对数据库的操作,为什么Elasticsearch并没有这些服务,凭什么除了new对象以外能直接用一个服务调用save进行保存呢?这个服务似乎还是以Repository结尾的。
之前我似乎把indexName称为仓库,基于同样的@Document(indexName=“XXX”)
索引,会形成一个仓库,而我们需要基于@Document(indexName=“XXX”)
下面的实体类,创建一个仓库的接口。
1 | import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; |
这下就能解释上一段的仓库服务接口是哪里来的了。
查看插入的数据
如果安装了kibana,可以打开localhost:5601,输入:
1 | GET /archives/_search |
可以查到保存的文件:
前端发起检索
不用写实现!
在仓库部分定义了List<ElasticsearchArchive> findByContent(String content);
但是并没有给出具体的实现,这是Spring Data Elasticsearch 提供的一个基础接口,它支持根据方法名自动生成查询实现。
因此可以根据合理的命名方式,让他自动实现功能:
1 |
|
上一节的演示中使用的就是findByContent(String content);
方法。