ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。ElasticSearch能够做到实时搜索并且稳定,可靠。
Document文档是指一个可被索引的基础信息单元,JSON格式。
Index索引是指一个拥有相似特征的document的集合,一个索引由一个名字来标识(必须全部是小写字母)
Type类型是指在一个索引中可以定义一种或多种类型,类型是索引的一个逻辑上的分类/分区,一个索引中可以存在很多Type
通俗易懂的讲,就是Document可以看作表中的一条记录,Index可以看作Database数据库,而Type就是里面的Table表。在安装完成后,即可使用对索引进行操作。关于ElasticSearch的安装步骤,此处不再叙述。
Spring Boot 2.2.5 集成 elasticsearch 6.8.6,实现全文搜索引擎其实简单,只需要引入spring-boot-starter-data-elasticsearch依赖,添加配置即可。spring-boot-starter-data-elasticsearch让我们可以像使用JPA一样去操作ElasticSearch。
1、在pom.xml文件中引入依赖包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
2、在application.properties文件中添加ElasticSearch连接信息
server.port=8080 #es 配置信息 spring.main.allow-bean-definition-overriding=true elasticsearch.host=127.0.0.1 elasticsearch.port=9300 elasticsearch.clustername=elasticsearch elasticsearch.search.pool.size=5
3、创建Elasticsearch配置类
package com.yoodb.study.demo08.config; import lombok.extern.slf4j.Slf4j; import org.elasticsearch.client.Client; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.transport.client.PreBuiltTransportClient; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories; import java.net.InetAddress; @Slf4j @Configuration @EnableElasticsearchRepositories(basePackages = "com.yoodb.study.demo08.service") public class ElasticsearchConfig { @Value("${elasticsearch.host}") private String esHost; @Value("${elasticsearch.port}") private int esPort; @Value("${elasticsearch.clustername}") private String esClusterName; @Value("${elasticsearch.search.pool.size}") private Integer threadPoolSearchSize; @Bean public Client client() throws Exception { Settings esSettings = Settings.builder() .put("cluster.name", esClusterName) .put("client.transport.sniff", true) .put("thread_pool.search.size", threadPoolSearchSize) .build(); return new PreBuiltTransportClient(esSettings) .addTransportAddress(new TransportAddress(InetAddress.getByName(esHost), esPort)); } @Bean(name="elasticsearchTemplate") public ElasticsearchOperations elasticsearchTemplateCustom() throws Exception { ElasticsearchTemplate elasticsearchTemplate; try { elasticsearchTemplate = new ElasticsearchTemplate(client()); return elasticsearchTemplate; } catch (Exception e) { return new ElasticsearchTemplate(client()); } } }
4、创建Article实体类
package com.yoodb.study.demo08.bean; import org.springframework.data.elasticsearch.annotations.DateFormat; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; import java.util.Date; @Document(indexName = "blog",type = "article") public class Article { /** * 主键ID */ @Field(type = FieldType.Keyword) private String id; /** * 文章标题 */ @Field(type = FieldType.Text, analyzer = "ik_max_word",searchAnalyzer = "ik_max_word") private String title; /** * 文章内容 */ @Field(type = FieldType.Text, analyzer = "ik_max_word",searchAnalyzer = "ik_max_word") private String content; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } }
关于上面类中使用的相关spring-boot-starter-data-elasticsearch引入包的注解含义,在文章开篇处简单介绍了,下面详细讲述一下各个参数的含义:
@Document 作用在类,标记实体类为文档对象,一般有两个属性
indexName:对应索引库名称
type:对应在索引库中的类型
shards:分片数量,默认分5片
replicas:副本数量,默认1份
@Id 作用在成员变量,标记一个字段作为id主键
@Field 作用在成员变量,标记为文档的字段,并指定字段映射属性
type:字段类型,取值是枚举:FieldType
index:是否索引,布尔类型,默认是true
store:是否存储,布尔类型,默认是false
analyzer和searchAnalyzer中参数名称保持一直,ik_max_word可以改成ik_smart。
ik_max_word和ik_smart的区别?
ik_max_word参数采用穷尽式的分词,比如“我爱家乡”,可能会分出“我”,“我爱”,“家乡”等,而ik_smart参数分的会比较粗,如上语句可能会分出“我爱”,“家乡”这样。如果想要搜索出的结果尽可能全,可以使用ik_max_word参数,如果需要结果尽可能精确,可以使用ik_smart参数。
5、继承ElasticsearchRepository接口
package com.yoodb.study.demo08.config; import com.yoodb.study.demo08.bean.Article; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; public interface ElasticRepository extends ElasticsearchRepository<Article, String> { }
ElasticsearchRepository的源码如下:
package org.springframework.data.elasticsearch.repository; import org.elasticsearch.index.query.QueryBuilder; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.core.query.SearchQuery; import org.springframework.data.repository.NoRepositoryBean; @NoRepositoryBean public interface ElasticsearchRepository<T, ID> extends ElasticsearchCrudRepository<T, ID> { <S extends T> S index(S var1); <S extends T> S indexWithoutRefresh(S var1); Iterable<T> search(QueryBuilder var1); Page<T> search(QueryBuilder var1, Pageable var2); Page<T> search(SearchQuery var1); Page<T> searchSimilar(T var1, String[] var2, Pageable var3); void refresh(); Class<T> getEntityClass(); }
6、创建IElasticService接口
package com.yoodb.study.demo08.service; import com.yoodb.study.demo08.bean.Article; import java.util.Iterator; import java.util.List; public interface IElasticService { public void save(Article article); public void saveAll(List<Article> list); public Iterator<Article> findAll(); public List<Article> findArticleByTitle(String title); }
7、创建ElasticServiceImpl实现类
package com.yoodb.study.demo08.service.impl; import com.yoodb.study.demo08.bean.Article; import com.yoodb.study.demo08.config.ElasticRepository; import com.yoodb.study.demo08.service.IElasticService; import org.elasticsearch.index.query.MatchQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @Service("elasticService") public class ElasticServiceImpl implements IElasticService { @Autowired private ElasticRepository elasticRepository; @Override public void save(Article article) { elasticRepository.deleteAll(); elasticRepository.save(article); } @Override public void saveAll(List<Article> list) { elasticRepository.saveAll(list); } @Override public Iterator<Article> findAll() { return elasticRepository.findAll().iterator(); } public List<Article> findArticleByTitle(String title) { //matchQuery 会对关键字分词后进行搜索 MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", title); QueryBuilders.commonTermsQuery("title",title); Iterable<Article> search = elasticRepository.search(matchQueryBuilder); Iterator<Article> iterator = search.iterator(); List<Article> list = new ArrayList<>(); while (iterator.hasNext()){ Article next = iterator.next(); list.add(next); } return list; } }
8、创建控制层Controller类
package com.yoodb.study.demo08; import com.yoodb.study.demo08.bean.Article; import com.yoodb.study.demo08.service.IElasticService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.*; @Log4j2 @RestController @RequestMapping("/elastic") public class ElasticController { @Autowired private IElasticService elasticService; @GetMapping("/init") public void init(){ String title = "关注“Java精选”微信公众号"; String content = "Java精选专注程序员推送一些Java开发知识,包括基础知识、各大流行框架" + "(Mybatis、Spring、Spring Boot等)、大数据技术(Storm、Hadoop、MapReduce、Spark等)、" + "数据库(Mysql、Oracle、NoSQL等)、算法与数据结构、面试专题、面试技巧经验、职业规划以及" + "优质开源项目等。其中一部分由小编总结整理,另一部分来源于网络上优质资源,希望对大家的学习" + "和工作有所帮助。"; Article article = createArticle(title, content); elasticService.save(article); title = "关注素文宅博客"; content = "素文宅博客主要关于一些Java技术类型文章分享。"; article = createArticle(title, content); List<Article> list = new ArrayList<>(); list.add(article); elasticService.saveAll(list); } public static Article createArticle(String title,String content){ UUID uuid = UUID.randomUUID(); String id = uuid.toString(); Article article = new Article(); article.setId(id); article.setTitle(title); article.setContent(content); return article; } @GetMapping("/all") public Iterator<Article> all(){ return elasticService.findAll(); } @GetMapping("/key") public List<Article> all(String title){ return elasticService.findArticleByTitle(title); } }
9、创建Application启动类
package com.yoodb.study.demo08; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SSD08Application { public static void main(String[] args) { SpringApplication.run(SSD08Application.class, args); } }
10、运行程序
1)启动ElasticSearch服务
访问地址:http://localhost:9200/
2)启动Spring Boot项目
2020-04-06 20:17:45.732 INFO 38068 --- [ main] o.elasticsearch.plugins.PluginsService : loaded plugin [org.elasticsearch.transport.Netty4Plugin] 2020-04-06 20:17:54.835 INFO 38068 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 2020-04-06 20:17:56.788 INFO 38068 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2020-04-06 20:17:56.791 INFO 38068 --- [ main] com.yoodb.study.demo08.SSD08Application : Started SSD08Application in 19.957 seconds (JVM running for 23.733)
3)访问地址
初始化生成索引文件访问地址
http://localhost:8080/elastic/init
获取所有索引内容访问地址
http://localhost:8080/elastic/all
返回结果:
[{"id":"62e73653-4658-4d72-9b2e-e541a3ae7d53","title":"关注“Java精选”微信公众号","content":"Java精选专注程序员推送一些Java开发知识,包括基础知识、各大流行框架(Mybatis、Spring、Spring Boot等)、大数据技术(Storm、Hadoop、MapReduce、Spark等)、数据库(Mysql、Oracle、NoSQL等)、算法与数据结构、面试专题、面试技巧经验、职业规划以及优质开源项目等。其中一部分由小编总结整理,另一部分来源于网络上优质资源,希望对大家的学习和工作有所帮助。"},{"id":"1e7c2f0b-e07e-4037-a3a3-3385d8b7d2c1","title":"关注素文宅博客","content":"素文宅博客主要关于一些Java技术类型文章分享。"}]
根据搜索条件,获取索引内容访问地址
http://localhost:8080/elastic/key?title=Java%E7%B2%BE%E9%80%89
返回结果:
[{"id":"62e73653-4658-4d72-9b2e-e541a3ae7d53","title":"关注“Java精选”微信公众号","content":"Java精选专注程序员推送一些Java开发知识,包括基础知识、各大流行框架(Mybatis、Spring、Spring Boot等)、大数据技术(Storm、Hadoop、MapReduce、Spark等)、数据库(Mysql、Oracle、NoSQL等)、算法与数据结构、面试专题、面试技巧经验、职业规划以及优质开源项目等。其中一部分由小编总结整理,另一部分来源于网络上优质资源,希望对大家的学习和工作有所帮助。"}]
项目源码
关于本篇文章的项目源码(springboot-study-demo08)地址:
https://github.com/yoodb/springboot
到此,Spring Boot 2.2.5 集成 ElasticSearch 框架,实现全文搜索引擎就讲完了,后续关于Spring Cloud系列文章也会持续更新,大家可以收藏起来,方便后面学习和参考。下面如果大家有时间的话可以试一试,有什么疑问欢迎下方留言。