這里不贅述Elasticsearch的相關基礎知識點和部署教程,着重講如何在SpringBoot框架中集成Elasticsearch
Spring Data項目中提供了操作es的框架Spring Data Elasticsearch,目前框架最新版本為4.0,根據Spring Data Elasticsearch的官方文檔描述,4.0版本的框架支持Elasticsearch版本最新為7.6,所以如果用了更新版本的Elasticsearch的話不建議使用Spring Data Elasticsearch集成,可能會出現問題
個人在學習Elasticsearch過程中,發現網上SpringBoot集成es操作的相關博客資料不是很多,大多數版本仍在使用TransportClient,TransportClient在Spring Data Elasticsearch 4.0官方文檔中已寫明不推薦使用,且普遍都比較簡略。Elasticsearch的版本迭代是很快的,所以建議大家在學習一些比較新的技術或框架的時候,最好是配合官方文檔進行資料查閱,有時能夠避免很多彎路
下面開始介紹如何在SpringBoot中集成
1、創建SpringBoot項目,引入Spring Data Elasticsearch依賴,目前默認版本是4.0
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>
2、配置文件
spring: application: name: es-demo elasticsearch: rest: uris: http://localhost:9200 #es服務器地址(默認) server: port: 8080
3、創建一個Book類,相當於Elasticsearch中的文檔,用於演示
@Document(indexName = "book") public class Book { //@Id注解表明該字段是文檔id @Id private Integer id; private String title; private BigDecimal price; @Field(type = FieldType.Keyword) private List<String> tag; //此處省略getter、setter、toString... }
現在項目已構建並配置完成,接着就可以使用Spring Data Elasticsearch框架提供的各種類進行操作了
用法一:基於JPA Repository的方式,繼承ElasticsearchRepository接口后,方法名按照框架要求的命名規則,就能創建各種各樣的條件查詢,適合一些比較簡單的查詢操作,更詳細的可以參考官方文檔
1、創建用於Book對象的增刪改查接口
@Repository public interface BookRepository extends ElasticsearchRepository<Book, Integer> { //findById()和save()之類的方法父接口已經寫了,這里無需重復編寫 //按價格區間查詢 List<Book> findByPriceBetween(BigDecimal min, BigDecimal max); //按書名查詢,因為使用了中文分詞器ik,所以這里並不是精確查詢 List<Book> findByTitle(String title); //按標簽匹配查詢 List<Book> findByTagIn(List<String> tags); }
接口寫好后,使用@Autowired注解自動注入即可使用,具體測試這里不贅述
用法二:使用ElasticsearchRestTemplate類操作,除了支持簡單數據增刪改查之外,還支持對索引進行操作;配合查詢條件/聚合構造器NavtiveQueryBuilder、QueryBuilders、AggregationBuilders,可以進行一些復雜的查詢和聚合操作,但需要對Elasticsearch的Query DSL比較熟悉
@SpringBootTest public class EsRestTemplateTest { //自動注入即可使用 @Autowired private ElasticsearchRestTemplate esRestTemplate; //按id查詢 @Test void testQueryBookById() { Book book = esRestTemplate.get("1", Book.class); Assertions.assertNotNull(book); System.out.println(book.toString()); } //按書名查詢 @Test void testQueryBookByTitle() { NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.matchQuery("title", "Java")) .build(); SearchHits<Book> searchHits = esRestTemplate.search(searchQuery, Book.class); //SearchHits就是查詢的結果集 searchHits.get().forEach(hit -> { System.out.println(hit.getContent()); }); } //聚合操作-計算所有書籍的平均價格 @Test void testAggregationBookAvgPrice() { //聚合名為avg_price,對price字段進行聚合,計算平均值 NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() .addAggregation(AggregationBuilders.avg("avg_price").field("price")) .build(); SearchHits<Book> searchHits = esRestTemplate.search(searchQuery, Book.class); searchHits.get().forEach(hit -> { System.out.println(hit.getContent()); }); //獲取聚合結果 if (searchHits.hasAggregations()) { ParsedAvg parsedAvg = searchHits.getAggregations().get("avg_price"); Assertions.assertNotNull(parsedAvg, "無聚合結果"); System.out.println(parsedAvg.getValue()); } }
//...... }
以上是ElasticsearchRestTemlpate類的簡單用法,其他用法可以自行探索,構造器的方法名都和Elasticsearch的Query DSL基本一致,所以如果對Query DSL比較熟悉的話,用起來也不會很難