1. Spring Data Elasticsearch
Spring Data Elasticsearch是Spring Data項目的子項目,提供了Elasticsearch與Spring的集成。實現了Spring Data Repository風格的Elasticsearch文檔交互風格,讓你輕松進行Elasticsearch客戶端開發。
2. 個人的一些看法
應粉絲要求特地將Elasticsearch整合到Spring Boot 中去。本來打算整合到kono腳手架中,但是轉念一想這樣並不是非常合適,一般搜索建議作為一個獨立的平台運作,小公司可作為一個獨立的服務,大公司可作為一個搜索中台。一般我認為雖然Elasticsearch提供了搜索功能,大部分情況下我們並不像常規的關系型數據庫一樣進行直接寫入,而是通過同步的方式進行同步或者預熱寫入數據。
具體的架構不是本文要講的,在ES的CSDN官方博客里面有比較具體的解決方案。本文是在你已經搭建好Elasticsearch集群的前提下進行的。
2. 版本對應
相關項目的版本對應關系如下:
Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Boot |
---|---|---|---|
Neumann | 4.0.x | 7.6.2 | 2.3.x |
Moore | 3.2.x | 6.8.6 | 2.2.x |
Lovelace | 3.1.x | 6.2.2 | 2.1.x |
Kay | 3.0.x | 5.5.0 | 2.0.x |
Ingalls | 2.1.x | 2.4.0 | 1.5.x |
根據我平常的做法,我選擇Elasticsearch 7.6.2和Spring Boot 2.3.3作為版本基准進行集成。
3. 依賴引入及配置
只需要引入下面的依賴就可以集成Elasticsearch :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
關於配置有兩種一種面向傳統的Restful:
spring:
elasticsearch:
rest:
# 逗號分隔的Elasticsearch實例使用的列表
uris: http://localhost:9200
# 鏈接超時時間
connection-timeout:
# 讀取超時時間
read-timeout:
# ES 用戶名
username:
# ES 密碼
password:
如果你都采用默認的配置,可以什么都不配置,包括
uris
。
另一種面向反應式:
spring:
data:
elasticsearch:
client:
# 反應式相關的配置
reactive:
# 端點
endpoints:
connection-timeout:
max-in-memory-size:
socket-timeout:
use-ssl:
username:
password:
這里配合的是Spring Webflux反應式框架,我個人其實更加傾向於此,但是作為目前的主流還是選擇了第一種。
務必保證
spring.data.elasticsearch.repositories.enabled = true
,否則無法使用Spring Data Repository模式。
4. 操作
這里演示面向傳統的Restful,一共有兩種風格。假如我們向寫入了Blog
:
{
"blogId": "132435553",
"blogTitle": "腳手架集成elasticsearch",
"author": "felord",
"content": "全稱為Object Storage Service,也叫對象存儲服務,是一種解決和處理離散單元的方法,可提供基於分布式系統之上的對象形式的數據存儲服務,具有可拓展、可管理、低成本等特點,支持中心和邊緣存儲,能夠實現存儲需求的彈性伸縮,主要應用於海量數據管理的各類場景。\n\n這概念真是夠難以理解的。簡單說點我知道的吧,平常我們的文件地址都是 /User/felord/video/xxx.mp4的目錄樹結構,系統先要找到User,然后一級一級往下找一直到目標為止,這是一種結構化的存儲方式。對象存儲就不一樣了,所有的文件都放在一個特定的池子里,只不過文件的攜帶有它自己的元信息,通過元信息去檢索文件。",
"url": "https://felord.cn/my-spring-boot-day7.html",
"publishedTime": "2020-08-30T22:17:40"
}
對應的POJO對象為:
/**
* @author felord.cn
* @since 2020/8/30 16:10
*/
@Document(indexName = "blogs")
@Data
public class Blog {
@Id
private String blogId;
private String blogTitle;
private String author;
private String content;
private String url;
@Field(type = FieldType.Date,format = DateFormat.date_hour_minute_second)
private LocalDateTime publishedTime;
}
@Document
用來標記文檔對象,包含了該文檔的一些元信息,索引副本數,分片數。@Id
文檔的標識符。@Field
文檔字段的一些元信息配置,類型、名稱、分詞器等等。
主要有以上三種,還有其它的一些注解標記,這里不再講述。
4.1 ElasticsearchRestTemplate
RedisTemplate
相信你已經不陌生了,同樣的,Spring Data Elasticsearch提供了ElasticsearchRestTemplate
來操作Elasticsearch,增刪改查應有盡有。這里演示進行復雜的Criteria查詢。
從blogs索引中查詢blogId為132435553而且包含elastic詞匯的標題的文檔,同時查詢詞匯高亮
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
@Test
void testTemplate() {
// 構造條件
Criteria criteria = Criteria.where(new SimpleField("blogId"))
.is("132435553")
.and(new SimpleField("blogTitle"))
.contains("elastic");
CriteriaQuery criteriaQuery = new CriteriaQuery(criteria);
// 高亮
HighlightBuilder blogTitle = SearchSourceBuilder.highlight().field("blogTitle");
HighlightQuery highlightQuery = new HighlightQuery(blogTitle);
criteriaQuery.setHighlightQuery(highlightQuery);
SearchHits<Blog> blogSearchHits = elasticsearchRestTemplate.search(criteriaQuery, Blog.class);
blogSearchHits.getSearchHits().forEach(System.out::println);
}
4.2 Spring Data Repository
Spring Data Repository的核心接口是Repository
。這個接口需要領域類(比如上面的Blog
)跟領域類的ID類型作為參數。這個接口主要是讓你能知道繼承這個類的接口的類型。CrudRepository
提供了對被管理的實體類的一些常用增刪改查方法。那么針對Elasticsearch提供了各種特色的接口:
Repository模式提供了一種利用方法名稱進行條件構造的查詢方式。
這種方式好處就是語義化,壞處就是方法名稱可能非常的長。對於4.1中的例子我們可以簡化為:
/**
* @author felord.cn
* @since 2020/8/30 21:32
*/
public interface BlogRepository extends ElasticsearchRepository<Blog,String> {
@Highlight(fields = {
@HighlightField(name = "blogTitle")
})
List<SearchHit<Blog>> searchBlogByBlogIdAndBlogTitleContains(String blogId, String titleContains);
}
另一種是采用注解方式,使用@Query
注解,比如我們根據blogId
進行查詢我們可以這么寫:
@Query("{\"match\": {\"blogId\": \"?0\" }}")
// @Query("{\"match\": {\"blogId\":{\"query\": \"?0\"}}}")
Blog searchById(String blogId);
這個優點就是更加靈活,而且寫法也更加隨意簡單;缺點就是需要熟悉Spring Data Elasticsearch以及Elasticsearch的查詢語法,有一定的學習成本。
總結
以上就是簡單的Spring Data Elasticsearch入門,對於使用Elasticsearch的項目來說,一般都具有了很大的數據量,所以要根據業務的需要進行具體的設計,Spring Data Elasticsearch能讓我們非常方便進行搜索操作,如果你在使用中遇到什么問題可以通過公眾號:碼農小胖哥留言進行討論。
關注公眾號:Felordcn 獲取更多資訊