一、ElasticSearch简介及安装
1. ES的简介
简介
我们的应用经常需要添加检索功能,开源的 ElasticSearch 是目前全文搜索引擎的首选。他可以快速的存储、搜索和分析海量数据。Spring Boot通过整合Spring Data ElasticSearch为我们提供了非常便捷的检索功能支持;
Elasticsearch是一个分布式搜索服务,提供Restful API,底层基于Lucene,采用多shard(分片)的方式保证数据安全,并且提供自动resharding的功能,github等大型的站点也是采用了ElasticSearch作为其搜索服务。
概念
以员工文档的形式存储为例:一个文档代表一个员工数据。存储数据到ElasticSearch 的行为叫做 索引 ,但在索引一个文档之前,需要确定将文档存储在哪里。
一个 ElasticSearch 集群可以包含多个 索引 ,相应的每个索引可以包含多个 类型 。 这些不同的类型存储着多个 文档 ,每个文档又有 多个 属性 。
索引(名词):
如前所述,一个 索引 类似于传统关系数据库中的一个 数据库 ,是一个存储关系型文档的地方。 索引 (index) 的复数词为 indices 或 indexes 。
索引(动词):
索引一个文档 就是存储一个文档到一个 索引 (名词)中以便被检索和查询。这非常类似于 SQL 语句中的 INSERT
关键词,除了文档已存在时,新文档会替换旧文档情况之外。
类似关系:
- 索引---数据库
- 类型---表
- 文档---表中的记录
- 属性---列
2. ES的安装与运行
与ES交互的端口说明:
- 9200端口
RESTful API通过HTTP通信
- 9300端口
Java客户端与ES的原生传输协议和集群交互
使用docker安装
# 拉取ES镜像
docker pull elasticsearch:7.6.1
#运行ES
docker run -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d -p 9200:9200 -p 9300:9300 --name ES01 elasticsearch:7.6.1
ES_JAVA_OPTS指定java虚拟机相关参数
- -Xms256m 初始堆内存大小为256m
- -Xmx256m 最大堆内存大小为256m
- discovery.type=single-node 设置为单点启动
ES默认占内存很大,默认占2G,所以,一般在启动时需要指定固定的内存大小,这里我们设置为 256M。
我们可以看到,ES已经启动了:
➜ ~ docker run -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d -p 9200:9200 -p 9300:9300 --name ES01 elasticsearch:7.6.1
7dee5f39cd0e50026cf56fa7d559fba0dd41fde81cf2d1b8a082a43213af2edc
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7dee5f39cd0e elasticsearch:7.6.1 "/usr/local/bin/dock…" 25 seconds ago Up 24 seconds 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp ES01
在浏览器访问:http://localhost:9200/
返回结果:
{
"name": "7dee5f39cd0e",
"cluster_name": "docker-cluster",
"cluster_uuid": "Yu2idrk6Sn6KbZE8r1-z6w",
"version": {
"number": "7.6.1",
"build_flavor": "default",
"build_type": "docker",
"build_hash": "aa751e09be0a5072e8570670309b1f12348f023b",
"build_date": "2020-02-29T00:15:25.529771Z",
"build_snapshot": false,
"lucene_version": "8.4.0",
"minimum_wire_compatibility_version": "6.8.0",
"minimum_index_compatibility_version": "6.0.0-beta1"
},
"tagline": "You Know, for Search"
}
表明我们的ES已经安装成功并可以成功访问了。
二、Springboot整合ElasticSearch
1. 概述
SpringBoot默认支持两种技术来和ES交互;
Jest(默认不生效)
- 需要导入jest的工具包(io.searchbox.client.JestClient)
- 从springboot 2.2.0以后被弃用
- SpringData ElasticSearch
版本适配说明:
Spring Data Elasticsearch | Elasticsearch |
---|---|
3.2.x | 6.8.1 |
3.1.x | 6.2.2 |
3.0.x | 5.5.0 |
2.1.x | 2.4.0 |
2.0.x | 2.2.0 |
1.3.x | 1.5.2 |
Springboot 2.2.6对应于 Spring Data Elasticsearch 3.2.6,即适配Elasticsearch 6.8.1
编写文件对应Javabean,指定索引名和类型
@Document(indexName = "ustc",type = "book")
public class Book {
private Integer id;
private String bookName;
private String author;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", bookName='" + bookName + '\'' +
", author='" + author + '\'' +
'}';
}
}
配置主机地址
方式一 配置类配置
注意:这种方式底层依赖于Http相关类,因此要导入web相关jar包
@Configuration
static class Config {
@Bean
RestHighLevelClient client() {
ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("localhost:9200")
.build();
return RestClients.create(clientConfiguration).rest();
}
}
方式二 spring配置文件指定
spring.elasticsearch.rest.uris=http://192.168.31.162:9200
在测试类中注入客户端
@Autowired
RestHighLevelClient highLevelClient;
创建索引
IndexRequest request = new IndexRequest("ustc", "book",
UUID.randomUUID().toString())
.source(Collections.singletonMap("feature", "high-level-rest-client"))
.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
IndexResponse index = highLevelClient.index(request, RequestOptions.DEFAULT);
System.out.println(index.toString());
下面为创建索引
{
"_index": "ustc",
"_type": "book",
"_id": "0dc9f47a-7913-481d-a36d-e8f034a6a3ac",
"_score": 1,
"_source": {
"feature": "high-level-rest-client"
}
}
得到索引
//分别指定要获取的索引、类型、id
GetRequest getRequest = new GetRequest("ustc","book","0dc9f47a-7913-481d-a36d-e8f034a6a3ac");
GetResponse documentFields = highLevelClient.get(getRequest, RequestOptions.DEFAULT);
System.out.println(documentFields);
2. ElasticsearchRestTemplate
ES有两个模板,分别为ElasticsearchRestTemplate
和ElasticsearchTemplate
分别对应于High Level REST Client和Transport Client(弃用),两个模板都实现了ElasticsearchOperations
接口,因此使用时我们一般使用ElasticsearchOperations
,具体实现方式由底层决定。
由于在AbstractElasticsearchConfiguration
中已经向容器中导入了ElasticsearchRestTemplate
,因此我们使用时可以直接注入
注入模板
@Autowired
ElasticsearchOperations elasticsearchOperations;
保存索引
Book book = new Book();
book.setAuthor("路遥");
book.setBookName("平凡的世界");
book.setId(1);
IndexQuery indexQuery = new IndexQueryBuilder()
.withId(book.getId().toString())
.withObject(book)
.build();
String index = elasticsearchOperations.index(indexQuery);
查询索引
Book book = elasticsearchOperations.queryForObject(GetQuery.getById("1"), Book.class);
3. Elasticsearch Repositories
编写相关Repository并继承Repository或ElasticsearchRepository,泛型分别为<查询类,主键>
public interface BookRepository extends Repository {
List findByBookNameAndAuthor(String bookName, String author);
}
查询的方法仅需按照一定规则命名即可实现功能,无需编写实现,如上findByBookNameAndAuthor()方法相当于ES的json查询
{
"query": {
"bool" : {
"must" : [
{ "query_string" : { "query" : "?", "fields" : [ "bookName" ] } },
{ "query_string" : { "query" : "?", "fields" : [ "author" ] } }
]
}
}
}
@Query
此外,还可以使用@Query
自定义请求json
interface BookRepository extends ElasticsearchRepository {
@Query("{\"match\": {\"name\": {\"query\": \"?0\"}}}")
Page findByName(String name,Pageable pageable);
}
若参数为John,相当于请求体为
{
"query": {
"match": {
"name": {
"query": "John"
}
}
}
}
更多ES与springboot整合内容见官方文档