文章首發(fā)于微信公眾號《程序員果果》
地址:https://mp.weixin.qq.com/s/f9eE7jsPNWAr1gQ0iF-kDw
本篇源碼:https://github.com/gf-huanchupk/SpringBootLearning
一擂橘、簡介
我們的應(yīng)用經(jīng)常需要添加檢索功能胳搞,開源的 ElasticSearch 是目前全文搜索引擎的 首選踪旷。他可以快速的存儲召庞、搜索和分析海量數(shù)據(jù)。Spring Boot通過整合Spring Data ElasticSearch為我們提供了非常便捷的檢索功能支持;
Elasticsearch是一個分布式搜索服務(wù)娄琉,提供Restful API,底層基于Lucene,采用 多shard(分片)的方式保證數(shù)據(jù)安全凰盔,并且提供自動resharding的功能,github 等大型的站點也是采用了ElasticSearch作為其搜索服務(wù)倦春,
二、安裝elasticsearch
我們采用 docker鏡像安裝的方式落剪。
#下載鏡像
docker pull elasticsearch
#啟動鏡像睁本,elasticsearch 啟動是會默認(rèn)分配2G的內(nèi)存 ,我們啟動是設(shè)置小一點忠怖,防止我們內(nèi)存不夠啟動失敗
#9200是elasticsearch 默認(rèn)的web通信接口呢堰,9300是分布式情況下,elasticsearch個節(jié)點通信的端口
docker run -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d -p 9200:9200 -p 9300:9300 --name es01 5c1e1ecfe33a
訪問 127.0.0.1:9200 如下圖凡泣,說明安裝成功
三枉疼、elasticsearch的一些概念
- 以 員工文檔 的形式存儲為例:一個文檔代表一個員工數(shù)據(jù)。存儲數(shù)據(jù)到 ElasticSearch 的行為叫做索引 鞋拟,但在索引一個文檔之前骂维,需要確定將文檔存 儲在哪里。
- 一個 ElasticSearch 集群可以 包含多個索引 贺纲,相應(yīng)的每個索引可以包含多個類型航闺。這些不同的類型存儲著多個文檔 ,每個文檔又有 多個 屬性 猴誊。
- 類似關(guān)系:
- 索引-數(shù)據(jù)庫
- 類型-表
- 文檔-表中的記錄 – 屬性-列
elasticsearch使用可以參早官方文檔潦刃,在這里不在講解。
四懈叹、整合 elasticsearch
創(chuàng)建項目 springboot-elasticsearch乖杠,引入web支持
SpringBoot 提供了兩種方式操作elasticsearch,Jest 和 SpringData澄成。
Jest 操作 elasticsearch
Jest是ElasticSearch的Java HTTP Rest客戶端胧洒。
ElasticSearch已經(jīng)有一個Java API笆包,ElasticSearch也在內(nèi)部使用它,但是Jest填補了空白略荡,它是ElasticSearch Http Rest接口缺少的客戶端庵佣。
1. pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gf</groupId>
<artifactId>springboot-elasticsearch</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot-elasticsearch</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>io.searchbox</groupId>
<artifactId>jest</artifactId>
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2. application.properties
spring.elasticsearch.jest.uris=http://127.0.0.1:9200
3. Article
package com.gf.entity;
import io.searchbox.annotations.JestId;
public class Article {
@JestId
private Integer id;
private String author;
private String title;
private String content;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
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;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder( "{\"Article\":{" );
sb.append( "\"id\":" )
.append( id );
sb.append( ",\"author\":\"" )
.append( author ).append( '\"' );
sb.append( ",\"title\":\"" )
.append( title ).append( '\"' );
sb.append( ",\"content\":\"" )
.append( content ).append( '\"' );
sb.append( "}}" );
return sb.toString();
}
}
4. springboot測試類
package com.gf;
import com.gf.entity.Article;
import io.searchbox.client.JestClient;
import io.searchbox.core.Index;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootElasticsearchApplicationTests {
@Autowired
JestClient jestClient;
@Test
public void createIndex() {
//1. 給ES中索引(保存)一個文檔
Article article = new Article();
article.setId( 1 );
article.setTitle( "好消息" );
article.setAuthor( "張三" );
article.setContent( "Hello World" );
//2. 構(gòu)建一個索引
Index index = new Index.Builder( article ).index( "gf" ).type( "news" ).build();
try {
//3. 執(zhí)行
jestClient.execute( index );
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void search() {
//查詢表達(dá)式
String query = "{\n" +
" \"query\" : {\n" +
" \"match\" : {\n" +
" \"content\" : \"hello\"\n" +
" }\n" +
" }\n" +
"}";
//構(gòu)建搜索功能
Search search = new Search.Builder( query ).addIndex( "gf" ).addType( "news" ).build();
try {
//執(zhí)行
SearchResult result = jestClient.execute( search );
System.out.println(result.getJsonString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
Jest的更多api ,可以參照github的文檔:https://github.com/searchbox-io/Jest
SpringData 操作 elasticsearch
1. application.properties
spring.data.elasticsearch.cluster-name=elasticsearch
spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300
2. Book
package com.gf.entity;
@Document( indexName = "gf" , 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() {
final StringBuilder sb = new StringBuilder( "{\"Book\":{" );
sb.append( "\"id\":" )
.append( id );
sb.append( ",\"bookName\":\"" )
.append( bookName ).append( '\"' );
sb.append( ",\"author\":\"" )
.append( author ).append( '\"' );
sb.append( "}}" );
return sb.toString();
}
}
3. BookRepository
package com.gf.repository;
import com.gf.entity.Book;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
public interface BookRepository extends ElasticsearchRepository<Book, Integer>{
List<Book> findByBookNameLike(String bookName);
}
4. springboot 測試類
package com.gf;
import com.gf.entity.Article;
import com.gf.entity.Book;
import com.gf.repository.BookRepository;
import io.searchbox.client.JestClient;
import io.searchbox.core.Index;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootElasticsearchApplicationTests {
@Autowired
BookRepository bookRepository;
@Test
public void createIndex2(){
Book book = new Book();
book.setId(1);
book.setBookName("西游記");
book.setAuthor( "吳承恩" );
bookRepository.index( book );
}
@Test
public void useFind() {
List<Book> list = bookRepository.findByBookNameLike( "游" );
for (Book book : list) {
System.out.println(book);
}
}
}
我們啟動測試 汛兜,發(fā)現(xiàn)報錯 巴粪。
這個報錯的原因是springData的版本與我elasticsearch的版本有沖突,下午是springData官方文檔給出的適配表粥谬。
我們使用的springdata elasticsearch的 版本是3.1.3 肛根,對應(yīng)的版本應(yīng)該是6.2.2版本,而我們是的 elasticsearch 是 5.6.9漏策,所以目前我們需要更換elasticsearch的版本為6.X
docker pull elasticsearch:6.5.1
docker run -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d -p 9200:9200 -p 9300:9300 --name es02 鏡像ID
訪問127.0.0.1:9200
集群名為docker-cluster派哲,所以我們要修改application.properties的配置了
spring.data.elasticsearch.cluster-name=docker-cluster
spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300
我們再次進行測試,測試可以通過了 掺喻。我們訪問http://127.0.0.1:9200/gf/book/1芭届,可以得到我們存入的索引信息。
源碼下載:https://github.com/gf-huanchupk/SpringBootLearning