天天看點

極簡教程 | Spring Boot整合Elasticsearch實作資料搜尋引擎

前面介紹了Elasticsearch的特點和優勢,接下來在Spring Boot項目中使用Elasticsearch一步一步地實作搜尋引擎的功能。

一、Spring Boot對Elasticsearch的支援

在沒有Spring Boot之前使用Elasticsearch非常痛苦,需要對Elasticsearch用戶端進行一系列的封裝等操作,使用複雜,配置煩瑣。所幸,Spring Boot提供了對Spring Data Elasticsearch的封裝元件

spring-boot-starter-data-elasticsearch,它讓Spring Boot項目可以非常友善地去操作Elasticsearch中的資料。

值得注意的是,Elasticsearch的5.x、6.x、7.x版本之間的差别還是很大的。Spring Data Elasticsearch、Spring Boot與Elasticsearch之間有版本對應關系,不同的版本之間不相容,Spring Boot 2.1對應的是Spring Data Elasticsearch 3.1.2版本。對應關系如表13-1所示。

表13-1 Spring Data Elasticsearch、Spring Boot與Elasticsearch的對應關系

Spring Data Elasticsearch Spring Boot Elasticsearch
3.2.x 2.2.x 6.8.4
3.1.x 2.1.x 6.2.2
3.0.x 2.0.x 5.5.0
1.5.x 2.4.0

這是官方提供的版本對應關系,建議按照官方的版本對應關系進行選擇,以避免不必要的麻煩。

二、Spring Boot操作Elasticsearch的方式

由于Elasticsearch和Spring之間存在版本相容的問題,導緻在Spring Boot項目中操作Elasticsearch的方式有很多種,如Repositories、JestClient、Rest API等。是以有必要梳理一下主流的Spring Boot操作Elasticsearch的方式。目前,Spring推薦使用Elasticsearch的方式,如下圖所示:

極簡教程 | Spring Boot整合Elasticsearch實作資料搜尋引擎

我們看到Spring Boot提供了ElasticSearchRepository和ElasticsearchRestTemplate實作索引資料的增删改查。

  • ElasticSearchRepository:繼承自Spring Data中的Repository接口,是以支援以資料庫的方式對資料進行增删改查的操作,而且支援已命名查詢等資料查詢。
  • ElasticsearchRestTemplate:spring-data-Elasticsearch項目中的一個類,和其他Spring項目中的Template類似。ElasticsearchRestTemplate是Spring對ES的Rest API進行的封裝,提供了大量相關的類來完成複雜的查詢功能。

三、在Spring Boot項目中內建Elasticsearch

Spring Boot提供的spring-boot-starter-data-Elasticsearch元件為我們提供了非常便捷的資料檢索功能。下面就來示範Spring Boot項目如何內建Elasticsearch。

1. 添加Elasticsearch依賴

首先在pom.xml中添加spring-boot-starter-data-Elasticsearch元件依賴,代碼如下:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-Elasticsearch</artifactId>
</dependency>      

2. 配置Elasticsearch

在application.properties項目配置檔案中添加Elasticsearch伺服器的位址,代碼如下:

spring.Elasticsearch.rest.uris=http://10.2.1.231:9200      

主要用來配置Elasticsearch服務位址,多個位址用逗号分隔。需要注意的是,Spring Data Elasticsearch各版本的配置屬性可能不一樣。本示例中使用的是7.6.2版本。

3. 建立文檔對象

建立實體對象類Book,然後使用@Document注解定義文檔對象,示例代碼如下:

@Document( indexName = "book" , replicas = 0)
public class Book {
    @Id
    private Long id;
    
    @Field(analyzer = "ik_max_word",type = FieldType.Text)
    private String bookName;
    
    @Field(type = FieldType.Keyword)
    private String author;
    
    private float price;
    
    private int page;
    
    @Field(type = FieldType.Keyword, fielddata = true)
    private String category;
    
    // 省略get、set方法
    
    public Book(){
    
    }
    
    public Book(Long id,String bookName, String author,float price,int page,String category) {
    
        this.id = id;
        this.bookName = bookName;
        this.author = author;
        this.price = price;
        this.page = page;
        this.category = category;
    }
    
    @Override
    public String toString() {
    
        final StringBuilder sb = new StringBuilder( "{\"Book\":{" );
            sb.append( "\"id\":" ).append( id );
            sb.append( ",\"bookName\":\"" ).append( bookName ).append( '\"' );
            sb.append( ",\"page\":\"" ).append( page ).append( '\"' );
            sb.append( ",\"price\":\"" ).append( price ).append( '\"' );
            sb.append( ",\"category\":\"" ).append( category ).append( '\"' );
            sb.append( ",\"author\":\"" ).append( author ).append( '\"' );
            sb.append( "}}" );
            
        return sb.toString();
    
    }
}      

如上面的示例所示,通過@Document注解将資料實體對象與Elasticsearch中的文檔和屬性一一對應。

(1)@Document注解會對實體中的所有屬性建立索引:

  • indexName = "customer":表示建立一個名為customer的索引。
  • type="customer":表示在索引中建立一個名為customer的類别,而在Elasticsearch 7.x版本中取消了類别的概念。
  • shards = 1:表示隻使用一個分片,預設為5。
  • replicas = 0:表示副本數量,預設為1,0表示不使用副本。
  • refreshInterval = "-1":表示禁止索引重新整理。

(2)@Id作用在成員變量,标記一個字段作為id主鍵。

(3)@Field作用在成員變量,标記為文檔的字段,并指定字段映射屬性:

  • type:字段類型,取值是枚舉:FieldType。
  • index:是否索引,布爾類型,預設是true。
  • store:是否存儲,布爾類型,預設是false。
  • analyzer:分詞器名稱是ik_max_word。

4. 建立操作的Repository

建立CustomerRepository接口并繼承ElasticsearchRepository,新增兩個簡單的自定義查詢方法。示例代碼如下:

public interface BookRepository extends ElasticsearchRepository<Book, Integer>{
        List<Book> findByBookNameLike(String bookName);
}      

通過上面的示例代碼,我們發現其使用方式和JPA的文法是一樣的。

5. 驗證測試

首先建立BookRepositoryTest單元測試類,在類中注入BookRepository,最後添加一個資料插入測試方法。

@Test
public void testSave() {
Book book = new Book();
book.setId(1);
book.setBookName("西遊記");
book.setAuthor("吳承恩");
repository.save(book);
Book newbook=repository.findById(1).orElse(null);
System.out.println(newbook);
}      

單擊Run Test或在方法上右擊,選擇Run 'testSave',運作單元測試方法,檢視索引資料是否插入成功,運作結果如下圖所示:

極簡教程 | Spring Boot整合Elasticsearch實作資料搜尋引擎

結果表明索引資料儲存成功,并且通過id能查詢到儲存的索引資料資訊,說明在Spring Boot中成功內建Elasticsearch。

最後

以上,介紹了Spring Boot項目中使用Elasticsearch,一步一步地實作搜尋引擎的功能。