概述
之前本人只简单使用过 Solr,而 Elasticsearch 与 solr 相比:
solr
优点
- solr有一个更大、更成熟的用户、开发和贡献者社区
- 支持添加多种格式的索引,如:HTML、PDF、微软 Office 系列软件格式以及 JSON、XML、CSV 等纯文本格式
- Solr比较成熟、稳定
- 不考虑建索引的同时进行搜索,速度更快
缺点
- 建立索引时,搜索效率下降,实时索引搜索效率不高
Elasticsearch
优点
- Elasticsearch是分布式的。不需要其他组件,分发是实时的,被叫做”Push replication”
- Elasticsearch 完全支持 Apache Lucene 的接近实时的搜索
- 处理多租户(multitenancy)不需要特殊配置,而Solr则需要更多的高级设置
- Elasticsearch 采用 Gateway 的概念,使得完备份更加简单
- 各节点组成对等的网络结构,某些节点出现故障时会自动分配其他节点代替其进行工作
缺点
- 还不够自动,不适合当前新的Index Warmup API (参考:http://zhaoyanblog.com/archives/764.html)
安装
使用 docker 进行安装,这里记录下启动命令的参数(默认初始占用2G堆内存空间):
docker run -e ES_JAVA_OPTS="-Xms256M -Xmx256m" -d -p 9200:9200 -p 9300:9300 --name [容器名] [镜像id]
访问:http://192.168.43.244:9200,看到如下页面则为成功:
入门
同样我们可以参考官方中文文档:Elasticsearch 权威指南
关于文档
Elasticsearch 使用 JSON 作为文档的序列化格式,如一个 user 对象:
{
"email": "john@smith.com",
"first_name": "John",
"last_name": "Smith",
"info": {
"bio": "Eco-warrior and defender of the weak",
"age": 25,
"interests": [ "dolphins", "whales" ]
},
"join_date": "2014/05/01"
}
关于索引
- 作为动词:存储数据到 Elasticsearch 的行为叫做 索引
- 作为名词:一个 索引 类似于传统关系数据库中的一个 数据库 ,是一个存储关系型文档的地方,如下图:
知道了上面的概念,我们就可以来在 Elasticsearch 中操作文档数据: - 索引一个文档: 发送 PUT 请求到 http://192.168.43.244:9200/megacorp/employee/1,并带上 JSON 文档数据,就会保存在相应索引下 id 为 1 的位置。
- 检索一个文档: 发送 GET 请求到 http://192.168.43.244:9200/megacorp/employee/1,即可获得 JSON 文档数据。
- 同样的,可以使用 DELETE 命令来删除文档,以及使用 HEAD 指令来检查文档是否存在。如果想更新已存在的文档,只需再次 PUT 。
不同的检索功能:
- 轻量搜索:/megacorp/employee/_search?q=last_name:Smith。
- 复杂搜索:使用查询表达式搜索,match 查询、范围查询 filter...。
{
"query" : {
"bool": {
"must": {
"match" : {
"last_name" : "smith"
}
},
"filter": {
"range" : {
"age" : { "gt" : 30 }
}
}
}
}
}
- 全文搜索:返回的数据会有 score 字段表示相关性得分。
{
"query" : {
"match" : {
"about" : "rock climbing"
}
}
}
- 短语搜索:只搜索出包含相应短语的文档。
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
}
}
- 高亮搜索:在每个搜索结果中 高亮 部分文本片段,返回结果与之前一样,与此同时结果中还多了一个叫做 highlight 的部分。这个部分包含了 about 属性匹配的文本片段,并以 HTML 标签 \\ 封装
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
},
"highlight": {
"fields" : {
"about" : {}
}
}
}
整合
创建项目:
自动添加我们的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
SpringBoot 默认支持两种技术与ES进行交互
- Jest:这种方式需要导入工具包(io.searchbox.client.JestClient)。
- SpringData ElasticSearch:自动配置类给我们提供了 Client(clusterNode、clusterName)、ElasticsearchTemplate、EasticsearchRepository 来操作 ES。
现在我们来使用 Jest 方式操作 ES:
- 注释掉 spring-boot-starter-data-elasticsearch,并引入 jest:
<dependency>
<groupId>io.searchbox</groupId>
<artifactId>jest</artifactId>
<version>5.3.3</version>
</dependency>
- 配置相关参数:
spring:
elasticsearch:
jest:
uris: http://192.168.50.130:9200
-
使用 JestClient 进行操作:
-
编写一个文档类Article
public class Article { @JestId //标识主键 private Integer id; private String author; private String title; private String contents; //getter/setter }
-
进行索引
@Autowired JestClient jestClient; //向es服务器索引一个文档 Article article = new Article(); article.setId(1); article.setAuthor("moke"); article.setTitle("test"); article.setContents("hello es"); //构建一个索引 Index index = new Index.Builder(article).index("moke").type("news").build(); try { jestClient.execute(index); } catch (IOException e) { e.printStackTrace(); }
-
全文搜索
String json = "{\n" + "\t\t \"query\" : {\n" + "\t\t \"match\" : {\n" + "\t\t \"contents\" : \"hello\"\n" + "\t\t }\n" + "\t\t }\n" + "\t\t}"; //构建搜索 Search search = new Search.Builder(json).addIndex("moke").addType("news").build(); try { SearchResult searchResult = jestClient.execute(search); System.out.println(searchResult.getJsonString()); } catch (IOException e) { e.printStackTrace(); }
-
使用SpringData ElasticSearch操作ES(注意版本):
- 解开我们前面的注释,配置基本信息:
spring:
data:
elasticsearch:
cluster-name: docker-cluster
cluster-nodes: 192.168.50.130:9300
- 编写文档类:
@Document(indexName = "moke",type = "book") //索引、类型
public class Book {
private Integer id;
private String bookName;
private String author;
//getter/setter
}
- ElasticsearchRepository操作ES:
public interface BookRepository<Book,Integer> extends ElasticsearchRepository {
public List<Book> findByBookNameLike(String key);
}
@Autowired
BookRepository bookRepository;
//索引文档
Book book = new Book();
book.setId(1);
book.setBookName("红楼梦");
book.setAuthor("曹雪芹");
bookRepository.index(book);
//自定义搜索
for(Book book : bookRepository.findByBookNameLike("红")){
System.out.println(book.toString());
}
其他方式参考官方文档:[地址](
异步