利用springboot+elasticSearch,实现数据高效搜索,实战开发

    技术2026-06-14  7

    每天早上七点三十,准时推送干货

    一、介绍

    在2018年10月5日,一个做数据搜索服务的软件初创公司 Elastic,在纳斯达克上市。

    而我们所熟悉的 ElasticSearch,正是 Elastic 公司最出名的产品之一,其中还包括有分布式日志解决方案 ELK(Elastic Search、Logstash、Kibana)、Beats、ECE等。

    那 ElasticSearch 究竟是干啥的呢?

    本质其实是一个基于 Lucene 开发的搜索服务器,它提供了一个基于 RESTful web 接口的分布式多用户能力的全文搜索引擎,能够达到实时搜索、稳定、可靠、快速、安装使用方便等特点。

    同时,作为 Apache 许可条款下的开放源码,目前已经成为一种流行的企业级搜索引擎。

    既然在企业开发中如此流行,肯定少不了 Springboot 的参与,今天我们就一起来探讨一下 SpringBoot 与 ElasticSearch 的整合,看看它是否真的如所介绍的那样优秀!

    本文主要介绍分为以下几个部分:

    第一部分:环境准备,安装ElasticSearch,安装 ElasticSearch-head 插件可视化web界面

    第二部分:SpringBoot 整合 ElasticSearch 开发

    第三部分:CRUD 测试

    二、ElasticSearch 安装

    为了和真实环境一致,我们采用CentOS7来部署 ElasticSearch 服务。

    建议把所需的安装包,手动从网上下载下来,因为服务器下载 ElasticSearch 安装包速度像蜗牛……,非常非常慢~~,可能是国内的网络原因吧!

    登录https://www.elastic.co/cn/downloads/elasticsearch,选择相应的系统环境下载软件包,小编我采用的是CentOS,所以选择Linux环境。

    2.1、安装JDK(已经安装过,可以跳过)

    Elasticsearch 是用 Java 语言开发的,所以在安装之前,需要先安装一下JDK

    yum -y install java-1.8.0-openjdk

    查看java安装情况

    java -version
    2.2、安装ElasticSearch

    进入到对应上传的文件夹,安装ElasticSearch

    rpm -ivh elasticsearch-6.1.0.rpm

    查找安装路径

    rpm -ql elasticsearch

    一般是装在/usr/share/elasticsearch/下。

    2.3、设置data的目录

    创建/data/es-data目录,用于elasticsearch数据的存放

    mkdir -p /data/es-data

    修改该目录的拥有者为elasticsearch

    chown -R elasticsearch:elasticsearch /data/es-data
    2.4、设置log的目录
    mkdir -p /log/es-log

    修改该目录的拥有者为elasticsearch

    chown -R elasticsearch:elasticsearch /log/es-log
    2.5、修改配置文件elasticsearch.yml
    vim /etc/elasticsearch/elasticsearch.yml

    修改如下内容:

    #设置节点名称 cluster.name: my-es #设置data存放的路径为/data/es-data path.data: /data/es-data #设置logs日志的路径为/log/es-log path.logs: /log/es-log #设置内存不使用交换分区,配置了bootstrap.memory_lock为true时反而会引发9200不会被监听,原因不明 bootstrap.memory_lock: false #设置允许所有ip可以连接该elasticsearch network.host: 0.0.0.0 #开启监听的端口为9200 http.port: 9200 #增加新的参数,为了让elasticsearch-head插件可以访问es (5.x版本,如果没有可以自己手动加) http.cors.enabled: true http.cors.allow-origin: "*"
    2.6、启动elasticsearch

    启动

    systemctl start elasticsearch

    查看状态

    systemctl status elasticsearch

    设置开机启动

    systemctl enable elasticsearch

    启动成功之后,测试服务是否开启

    curl -X GET http://localhost:9200

    返回如下信息,说明安装、启动成功了

    同时也可以远程测试一下,如果网络被拒绝,检查防火墙是否开启

    #查询防火墙状态 firewall-cmd --state

    如果状态是active表示已经开启,可以将其关闭

    #关闭防火墙 systemctl stop firewalld.service

    如果不想开机启动,可以输入如下命令

    #禁止firewall开机启动 systemctl disable firewalld.service

    我们再来测试一下远程是否可以正常访问,结果如下:

    已经可以正常访问了。

    三、ElasticSearch-head 安装

    上面我们介绍了 ElasticSearch 的安装,但是只能通过接口去查询数据,能不能通过可视化界面来查询数据呢?

    ElasticSearch-head,就是一个提供可视化界面的 ElasticSearch 插件,使用 Html5 开发,本质上还是一个 nodejs 的工程,因此在使用之前需要先安装 nodeJs。

    3.1、安装 nodeJs

    下载nodeJS

    wget https://nodejs.org/dist/v10.9.0/node-v10.9.0-linux-x64.tar.gz

    解压下载包

    tar -zxvf node-v10.9.0-linux-x64.tar.gz

    移动解压之后的文件夹到/usr/local

    mv node-v10.9.0-linux-x64 /usr/local/nodejs

    创建软链接,让npm和node命令全局生效

    ln -s /usr/local/nodejs/bin/node /usr/bin/node ln -s /usr/local/nodejs/bin/npm /usr/bin/npm

    查看nodejs是否安装成功

    node -v npm -v
    3.2、 安装 elasticsearch-head

    如果未安装git ,则先安装git工具

    yum install –y git

    查看git安装情况

    git --version

    从 gitHub 上拉取 elasticsearch-head 插件代码

    git clone https://github.com/mobz/elasticsearch-head.git

    进入elasticsearch-head文件夹

    cd elasticsearch-head

    因为npm安装非常非常慢,所以在这里先安装淘宝源地址,命令如下:

    npm install cnpm -g --registry=https://registry.npm.taobao.org

    创建cnpm软链接,不然执行下面执行命令会报错

    ln -s /usr/local/nodejs/bin/cnpm /usr/local/bin/cnpm

    使用cnpm命令下载安装项目所需要的插件

    cnpm install

    大概2分钟之后就安装好了,安装完成之后,修改配置信息

    vim _site/app.js

    将localhost换成elasticsearch的服务器地址,小编部署的这台是197.168.24.207。

    换完之后,在elasticsearch-head目录下,输入如下命令,进入启动目录

    cd node_modules/grunt/bin

    使用如下命令启动服务,使elasticsearch-head服务在后台运行!

    nohup ./grunt server &

    最后,直接远程通过浏览器访问elasticsearch-head可视化管理界面,默认访问地址是ip:9100,访问结果如下!

    至此,elasticsearch的安装包括可视化界面插件elasticsearch-head已经完成了!

    四、SpringBoot 整合 ElasticSearch

    对于 SpringBoot 来说,ElasticSearch 其实只是一个中间件,用途在于提供高效的搜索服务,比较幸运的是 SpringBoot 也为我们提供了 ElasticSearch 依赖库,添加依赖包,通过 JPA 访问非常方便,整合过程如下!

    4.1、创建一个SpringBoot项目

    在pom.xml中,添加依赖库 ElasticSearch 依赖包

    <!--jpa 支持--> <dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!--elasticsearch--> <dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>

    在application.properties中添加配置,其中节点名称cluster-name需要与上面的配置保持一致!

    spring.data.elasticsearch.cluster-name=my-es spring.data.elasticsearch.cluster-nodes=197.168.24.207:9300

    4.1、编写 CURD

    我们先写一个的实体类Student,借助这个实体类来完成基础的 CRUD 功能。

    新增实体类Student,其中indexName表示索引,type表示索引类别

    @Data @Accessors(chain = true) @Document(indexName = "student", type = "school") public class Student {     private static final long serialVersionUID = 1l;     @Id     private String id;     private String name;     private String gender;     private Integer age; }

    注意id字段是必须的,可以不写注解@Id!

    使用 JPA 作为数据持久层,接口继承自ElasticsearchRepository,同时新增两个自定义查询方法

    public interface StudentRepository extends ElasticsearchRepository<Student, String> {     /**      * 通过姓名模拟查询学生信息      * @param keyword      * @return      */     List<Student> findByNameLike(String keyword);     /**      * 自定义查询,固定匹配查询学生信息      * @param keyword      * @return      */     @Query("{\"match_phrase\":{\"name\":\"?0\"}}")     List<Student> findByNameCustom(String keyword); }

    创建控制层,编写基础的 CRUD 功能

    @RestController @RequestMapping("/student") public class StudentController {     @Autowired     private StudentRepository studentRepository;     @Autowired     private ElasticsearchTemplate elasticsearchTemplate;     /**      * 批量添加      * @param students      * @return      */     @PostMapping("/batchAdd")     public void add(@RequestBody List<Student> students){         studentRepository.saveAll(students);     }     /**      * 添加      * @param student      * @return      */     @PostMapping("/add")     public void add(@RequestBody Student student){         studentRepository.save(student);     }     /**      * 修改      * @param student      * @return      */     @PostMapping("/update")     public void updateById(@RequestBody Student student){         studentRepository.save(student);     }     /**      * 删除      * @param id      * @return      */     @PostMapping("/delete/{id}")     public void deleteById(@PathVariable String id){         studentRepository.deleteById(id);     }     /**      * 获取所有信息      * @return      */     @GetMapping("/get")     public Object getAll(){         Iterable<Student> iterable = studentRepository.findAll();         List<Student> list = new ArrayList<>();         iterable.forEach(list :: add);         return list;     }     /**      * 查询指定ID      * @param id      * @return      */     @GetMapping("/get/{id}")     public Object getById(@PathVariable String id){         if(StringUtils.isEmpty(id)){             return Result.error();         }         Optional<Student> studentOptional = studentRepository.findById(id);         if(studentOptional.isPresent()){             return studentOptional.get();         }         return null;     }     /**      * 普通搜索      * @param keyword      * @return      */     @GetMapping("/search/name")     public Object searchName(String keyword){         List<Student> students = studentRepository.findByNameLike(keyword);         return students;     }     /**      * 自定义匹配      * 普通搜索      * @param keyword      * @return      */     @GetMapping("/search/name/custom")     public Object searchTitleCustom(String keyword){         List<Student> students = studentRepository.findByNameCustom(keyword);         return students;     }     /**      * 高级搜索,可以自定义添加搜索字段      * @param keyword      * @return      */     @GetMapping("/top/search/name")     public Object topSearchTitle(String keyword){         SearchQuery searchQuery = new NativeSearchQueryBuilder()                 .withQuery(queryStringQuery(keyword))                 .build();   //使用searchQuery进行搜索         List<Student> students = elasticsearchTemplate.queryForList(searchQuery, Student.class);         return students;     } }

    4.2、CRUD 测试

    CRUD 编写完了,我们验证一下是否可以正常操作,启动 springboot 项目,使用 postman 进行测试。

    批量新增、新增功能测试

    执行之后,登录可视化界面查询界面,选择索引student,可以很清晰的看到数据已经进去了

    修改功能测试,修改时需要传入ID

    将王小贱从26岁修改为30岁,登录可视化界面查询数据也已经修改成功!

    删除功能测试,只需要传入ID

    删除李四,登录可视化界面查询数据也已经删除成功!

    查询功能测试,查询所有数据

    查询功能测试,查询指定ID信息

    查询功能测试,普通模糊查询,ElasticSearch 会对关键词进行拆分,只要有包含关键字的都会查询出来,例如输入王张,会将包含王或者张的姓名信息查询出来

    查询功能测试,高级查询,这个是使用官方api提供的查询入口,可以在方法中进行自定义搜索

    五、总结

    elasticsearch 在海量数据查询方面,非常高效,本来想写在大量数据查询方面,数据库与 elasticsearch 的查询效率比对,由于篇幅较长会造成阅读体验降低,后在下篇文章中再次介绍这个部分。

    对于想学习 elasticsearch 的新手,尤其是安装部分可能比较困难,因此花的编写时间比较多,后续的整合都比较简单,elasticsearch 真正的强大的地方在于高效信息搜索,本篇对 elasticsearch 的搜索只是做一个基础的介绍,具体的高级搜索方法大家可以参考官方文档 API,本篇可以看作为 elasticsearch 搜索服务入门的教程,可能也有遗漏的地方,欢迎网友点评、吐槽!

    后说两句(求关注)

    最近大家应该发现微信公众号信息流改版了吧,再也不是按照时间顺序展示了。这就对阿粉这样的坚持的原创小号主,可以说非常打击,阅读量直线下降,正反馈持续减弱。

    所以看完文章,哥哥姐姐们给阿粉来个在看吧,让阿粉拥有更加大的动力,写出更好的文章,拒绝白嫖,来点正反馈呗~。

    如果想在第一时间收到阿粉的文章,不被公号的信息流影响,那么可以给Java极客技术设为一个星标。

    最后感谢各位的阅读,才疏学浅,难免存在纰漏,如果你发现错误的地方,由于本号没有留言功能,还请你在后台留言指出,我对其加以修改。

    最后谢谢大家支持~

    最最后,重要的事再说一篇~

    快来关注我呀~快来关注我呀~快来关注我呀~

    < END >

    如果大家喜欢我们的文章,欢迎大家转发,点击在看让更多的人看到。也欢迎大家热爱技术和学习的朋友加入的我们的知识星球当中,我们共同成长,进步。

    Processed: 0.008, SQL: 9