一、ElasticSearch简介
我们的应用经常需要添加检索功能,开源的 ElasticSearch 是目前全文搜索引擎的首选。他可以快速的存储、搜索和分析海量数据。Spring Boot通过整合Spring Data ElasticSearch为我们提供了非常便捷的检索功能支持;
Elasticsearch是一个分布式搜索服务,提供Restful API,底层基于Lucene,采用多shard(分片)的方式保证数据安全,并且提供自动resharding的功能,github等大型的站点也是采用了ElasticSearch作为其搜索服务.
能实现类似于Solr的站内搜索。
二、ElasticSearch部署与使用
通过docker去运行ElasticSearch容器,因为ElasticSearch可以支持使用Rest风格的Http请求进行对其操作。
ElasticSearch可以使用基于HTTP协议,以JSON为数据交互格式的RESTful API
1.简介一下ElasticSearch的名词概念:
索引(Indices):索引(名词) 一个索引(index)就像是传统关系数据库中的数据库,它是相关文档存储的地方,index的复数是indices 或indexes。
索引(动词) 「索引一个文档」表示把一个文档存储到索引(名词)里,类似于SQL中的insert
类型(type):一个索引可以包含多个类型,类似于SQL中的表
文档(documents):每个类型可以包含多个文档,类似于SQL中每一行数据
列(Fields):每个文档包含多个字段(Fields)(列)。类似于SQL中的列
Relational DB -> Databases -> Tables -> Rows -> Columns Elasticsearch -> Indices -> Types -> Documents -> Fields
2.使用docker将ElesticSearch部署到linux
要注意一点,ElesticSearch在启动的时候需要吃内存,如果虚拟机内存小可能会导致启动后几十秒就自动崩溃,解决方案:
关于docker启动ElasticSearch自动崩溃的解决方案
9200端口是用来进行web操作的,9300端口是用来集群之间通信的,所以我们这里暂时只用到了9200端口。
运行起来没问题之后,我们可以浏览器输入http://IP:9200访问
证明部署成功
可以通过向这个url发送一个uri为/megacorp/employee/1的PUT请求来进行文档的添加,发送的请求行为要添加的内容的json串
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
删除则向对应的URL发DELETE请求即可
更新可以通过向指定URL发送POST请求,如果文档存在则默认会覆盖。
可以通过向指定URL发送HEAD请求来检查某文档是否存在
查询特定文档可以向指定URL发送get请求,例如:
GET /megacorp/employee/1
响应的内容中包含一些文档的元信息
查询某索引下某类型的全部文档可以向指定URL发送GET请求,例如:
GET /megacorp/employee/_search
可以通过
GET /megacorp/employee/_search?q=last_name:Smith
进行指定字符串查询
但查询字符串搜索便于通过命令行完成特定(ad hoc)的搜索,但是它也有局限性(参阅简单搜索章节)。Elasticsearch提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、强大的查询。
DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。我们可以这样表示之前关于“Smith”的查询:
GET /megacorp/employee/_search
{
"query" : {
"match" : {
"last_name" : "Smith"
}
}
}
这会返回与之前查询相同的结果。你可以看到有些东西改变了,我们不再使用查询字符串(query string)做为参数,而是使用请求体代替。这个请求体使用JSON表示,其中使用了match
语句。
3.SpringBoot进行整合
这里我们使用SpringData对ElasticSearch进行整合
依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>
查看依赖后发现,SpringBoot2.1.4采用的elasticsearch是6.4.3版本
为了确保不出问题,我重新下载6.4.3版本,事后我验证了,就以下的这些基本操作,es的版本可以不影响
package org.dreamtech.esdemo.domain;
import java.io.Serializable;
import org.springframework.data.elasticsearch.annotations.Document;
/**
* 文章对象
*
* @author Xu Yiqing
*
*/
@Document(indexName = "blog", type = "article")
public class Article implements Serializable {
private static final long serialVersionUID = 8210249797764830332L;
private long id;
private String title;
private String summary;
private String content;
private int pv;
public long getId() {
return id;
}
public void setId(long 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;
}
public int getPv() {
return pv;
}
public void setPv(int pv) {
this.pv = pv;
}
}
配置文件
spring.data.elasticsearch.cluster-name=elasticsearch
spring.data.elasticsearch.cluster-nodes=IP:9300
spring.data.elasticsearch.repositories.enabled=true
对ES进行默认操作的接口
package org.dreamtech.esdemo.repository;
import org.dreamtech.esdemo.domain.Article;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Component;
@Component
public interface ArticleRepository extends ElasticsearchRepository<Article, Long> {
}
Controller层进行测试
@RestController
public class ArticleController {
@Autowired
private ArticleRepository articleRepository;
@GetMapping("/save")
public Object save(long id, String title) {
Article article = new Article();
article.setId(id);
article.setPv(123);
article.setContent("Springboot整合Elasticsearch");
article.setTitle(title);
article.setSummary("搜索框架整合");
articleRepository.save(article);
return "save";
}
@GetMapping("/search")
public Object search(String title) {
QueryBuilder queryBuilder = QueryBuilders.matchQuery("title", title);
Iterable<Article> list = articleRepository.search(queryBuilder);
return list;
}