SpringBoot 集成 Elasticsearch 实现全文搜索
一、安装 Elasticsearch
1、所需环境
Elasticsearch 5.5.0
Spring Data Elasticsearch 3.0.0.M4
2、build.gradle
我们需要添加 Spring Data Elasticsearch 的依赖 Spring Boot 提供了相关的 Starter 来实现 Spring Data Elasticsearch 开箱即用的功能,所以只需要在 build.gradle 文件中添加 Spring Data Elasticsearch Starter 的库即可。
// 依赖关系
dependencies {
// ...
// 添加Spring Data Elasticsearch 的依赖
compile (’ org.springframework.boot:spring-boot-starter-data-elasticsearch ’)
// ...
}
3、下载并安装 Elasticsearch
下载并解压,有一个名为 elasticsearch-5.5.0 的文件 ,将其称为%ES_HOME% 变量 在终端窗口中,切换到 %ES HOME%
例如,
> cd d:\elasticsearch-5.5.0
运行与停止服务
> .\bin\elasticsearch
... ...
可以输入 Ctr +C 来停止服务
4、配置
默认情况下,/config/elasticsearch.yml 文件加载其配置。也可以使用 -E 语法指定能在配置文件中指定的任何设置, 如下所
./bin/elasticsearch -Ecluster.name=my_cluster -Enode.name=node_1
注意:包含空格的值必须加上双引号,例如,-Epath.logs="C:\My Logs\logs".
提示:通常,任何集群范围的设置(如 cluster.name)都应该添加到 elasticsearch.yml 文件中,而任何特定于节点的设置(如 node.name )都可以在命令行中指定。
5、确认运行情况
可以通过向 localhost 上的端口 9200 发送 HTTP GET 请求来测试 Elasticsearch 节点是否正在运行。如下:
http://localhost:9200/
6、作为 Windows 服务
执行 bin 目录下的 elasticsearch service.bat 即可,允许用户从命令行来安装、删除、管理或配置服务,并能启动和停止服务
> cd D:\elasticsearch-5.5.0\bin
> elasticsearch-service.bat
Usage: elasticsearch-service. bat install | remove | start | stop | manager [SERVICE ID]
成功安装为 Windows 服务后,可以看到控制台信息提示。
二、Elasticsearch 实战
这里使用 Elasticsearch 来存储文本数据,并通过 Spring Data Elasticsearch 快速实现访问 Elasticsearch 数据的能力。
1、启动 Elasticsearch
首先,要确保已经可以正确启动 Elasticsearch 服务器了。 Linux 下运行 bin/elasticsearch, Windows 平台则运行 bin\elasticsearch. bat
2、修改 application.properties
相关的两项配置,如下:
# Elasticsearch 服务地址
spring.data.elasticsearch.cluster-nodes=localhost:9300
# 设置连接超时时间
spriηg data.elasticsearch.properties transport.tcp.connect timeout=l20s
其中,一个配置是为了配置 Elasticsearch 服务地址,另一个则是设置连接超时时间。
3、创建文档类
创建一个注解为 Document 的文档类 EsBlog,专门用于 Elasticsearch 中存储博客的文档。
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
@Document(indexName = "blog", type = "blog")
public class EsBlog implements Serializable {
private static final long serialVersionUID = lL;
@Id
private String id;
private String title;
private String summary;
private String content;
// JPA 的规范要求无参构造函数;设为 protected 防止直接使用
protected EsBlog(){}
protected EsBlog(String title,String summary,String content){
this.title = title;
this.summary = summary;
this.content = 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 getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString(){
return String.format("EsBlog[id=%s,title='%s',summary='%s',content='%s']",id, title , summary , content) ;
}
}
需要注意的是,在 Elasticsearch 中,主键 id 采用 String 类型。
4、创建资源库
es 包下定义资源库的接口 EsBlogRepository,该接口继承自 org.springframework.data.elasticsearch.repository.ElasticsearchRepository。
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface EsBlogRepository extends ElasticsearchRepository<EsBlog,String> {
/**
* 分页查询博客
*
* @param title
* @param summary
* @param content
* @param pageable
* @return
*/
Page<EsBlog> findByTitleContainingOrSummaryContainingOrContentContaining(String title, String summary, String content, Pageable pageable);
}
5、创建资源库测试用例
在 test 目录下建立 es包,创建资源库测试用例 EsBlogRepositoryTest,如下:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class EsBlogRepositoryTest {
@Autowired
private EsBlogRepository esBlogRepository;
@Before
public void initRepositoryData() {
// 清除所有数据
esBlogRepository.deleteAll();
// 初始化数据
esBlogRepository.save(new EsBlog("Had I not seen the Sun",
"I could have borne the shade",
"But Light a newer Wilderness. My Wilderness has made."));
esBlogRepository.save(new EsBlog("There is room in the halls of pleasure",
"For a long and lordly train",
"But one by one we must all file on, Through the narrow aisles of pain."));
esBlogRepository.save(new EsBlog("When you are old",
"When you are old and grey and full of sleep",
"And nodding by the fire,take down this book."));
}
@Test
public void testFindDistinctEsBlogByTitleContainingOrSummaryContainingOrContentContaining() {
Pageable pageable = PageRequest.of(0, 20);
String title = "Sun";
String summary = "is";
String content = "down";
Page<EsBlog> page = esBlogRepository.findByTitleContainingOrSummaryContainingOrContentContaining(title, summary, content, pageable);
System.out.println("---------start 1");
for (EsBlog blog : page) {
System.out.println(blog.toString());
}
System.out.println("---------end 1");
title = "the";
summary = "the";
content = "the";
page = esBlogRepository.findByTitleContainingOrSummaryContainingOrContentContaining(title, summary, content, pageable);
System.out.println("---------start 2");
for (EsBlog blog : page) {
System.out.println(blog.toString());
}
System.out.println("---------end 2");
}
}
其中, Pageable pageable = PageRequest.of(0, 20); 是初始化一个分页请求。
在执行测试用例之前,先在 Elasticsearch 的存储库中初始化了3首诗,作为测试用的数据;而后,执行测试,并能看到搜索的结果,并将结果从控制台进行了输出
6、创建控制器
创建控制器 BlogController 用于处理博客相关的请求,如下:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* Blog 控制器.
*
* @since
* @author
*/
@RestController
@RequestMapping("/blogs")
public class BlogController {
@Autowired
private EsBlogRepository esBlogRepository;
@GetMapping
public List<EsBlog> list(@RequestParam(value="title",required=false,defaultValue="") String title,
@RequestParam(value="summary",required=false,defaultValue="") String summary,
@RequestParam(value="content",required=false,defaultValue="") String content,
@RequestParam(value="pageIndex",required=false,defaultValue="0") int pageIndex,
@RequestParam(value="pageSize",required=false,defaultValue="10") int pageSize) {
// 数据在 Test 里面先初始化了,这里只管取数据
Pageable pageable = PageRequest.of(pageIndex, pageSize);
Page<EsBlog> page = esBlogRepository.findByTitleContainingOrSummaryContainingOrContentContaining(title, summary, content, pageable);
return page.getContent();
}
}
7、运行
在启动项目之前,要确保 Elasticsearch 服务器已经启动 在启动项目之后,运行 EsBlogRepositoryTest 测试用例来帮助初始化数据。
而后就能访问控制器所定义的 API ,如:http://localhost:8080/blogs?title=i&summary=love&content=you。