Java框架集成ES
1、SpringData Elasticsearch框架集成
1.1、SpringData 框架基本介紹
Spring Data是一個用于簡化數據庫、非關系型數據庫、索引庫訪問,并支持云服務的開源框架。其主要目標是使得對數據的訪問變得方便快捷,并支持 map-reduce框架和云計算數據服務。Spring Data可以極大的簡化JPA(Elasticsearch…)的寫法,可以在幾乎不用寫實現的情況下,實現對數據的訪問和操作。除了CRUD 外,還包括如分頁、排序等一些常用的功能。
Spring Data 的官網:https://spring.io/projects/spring-data
Spring Data 常用的功能模塊如下:

1.2、Spring Data Elasticsearch 框架基本介紹
Spring Data Elasticsearch 基于 spring data API 簡化 Elasticsearch 操作,將原始操作Elasticsearch 的客戶端 API 進行封裝 。Spring Data 為 Elasticsearch 項目提供集成搜索引擎。Spring Data Elasticsearch POJO 的關鍵功能區域為中心的模型與 Elastichsearch 交互文檔和輕松地編寫一個存儲索引庫數據訪問層。官方網站: https://spring.io/projects/spring-data-elasticsearch
Spring Data Elasticsearch 版本對比:

1.3、搭建Spring Data Elasticsearch框架項目
首先創建一個簡單的 java se Maven 項目,然后修改pom文件,增加依賴,如下:
<?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> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.6.RELEASE</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> </dependency> </dependencies> </project>
在 resources 目錄中增加application.properties文件,內容如下:
# es 服務地址 elasticsearch.host=127.0.0.1 # es 服務端口 elasticsearch.port=9200 # 配置日志級別,開啟 debug 日志 logging.level.com.atguigu.es=debug
Spring Boot 主程序:
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class MainApplication { public static void main(String[] args) { SpringApplication.run(MainApplication.class, args); } }
數據實體類:
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; @Data @NoArgsConstructor @AllArgsConstructor @ToString @Document(indexName = "shopping", shards = 3, replicas = 1) public class Product { //必須有 id,這里的 id 是全局唯一的標識,等同于 es 中的"_id" @Id private Long id;//商品唯一標識 /** * type : 字段數據類型 * analyzer : 分詞器類型 * index : 是否索引(默認:true) * Keyword : 短語,不進行分詞 */ @Field(type = FieldType.Text, analyzer = "ik_max_word") private String title;//商品名稱 @Field(type = FieldType.Keyword) private String category;//分類名稱 @Field(type = FieldType.Double) private Double price;//商品價格 @Field(type = FieldType.Keyword, index = false) private String images;//圖片地址 }
配置類
- ElasticsearchRestTemplate是spring-data-elasticsearch項目中的一個類,和其他spring項目中的 template 類似。
- 在新版的spring-data-elasticsearch 中,ElasticsearchRestTemplate 代替了原來的ElasticsearchTemplate。
- 原因是ElasticsearchTemplate基于TransportClient,TransportClient即將在8.x 以后的版本中移除。所以,我們推薦使用ElasticsearchRestTemplate。
- ElasticsearchRestTemplate基于RestHighLevelClient客戶端的。需要自定義配置類,繼承AbstractElasticsearchConfiguration,并實現elasticsearchClient()抽象方法,創建RestHighLevelClient對象。
AbstractElasticsearchConfiguration源碼:
package org.example; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.context.annotation.Bean; import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; public abstract class AbstractElasticsearchConfiguration extends ElasticsearchConfigurationSupport { //需重寫本方法 public abstract RestHighLevelClient elasticsearchClient(); @Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" }) public ElasticsearchOperations elasticsearchOperations(ElasticsearchConverter elasticsearchConverter) { return new ElasticsearchRestTemplate(elasticsearchClient(), elasticsearchConverter); } }
需要自定義配置類,繼承AbstractElasticsearchConfiguration,并實現elasticsearchClient()抽象方法,創建RestHighLevelClient對象,如下:
import lombok.Data; import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration; @ConfigurationProperties(prefix = "elasticsearch") @Configuration @Data public class ElasticsearchConfig extends AbstractElasticsearchConfiguration{ private String host ; private Integer port ; //重寫父類方法 @Override public RestHighLevelClient elasticsearchClient() { RestClientBuilder builder = RestClient.builder(new HttpHost(host, port)); RestHighLevelClient restHighLevelClient = new RestHighLevelClient(builder); return restHighLevelClient; } }
DAO 數據訪問對象
import com.lun.model.Product; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import org.springframework.stereotype.Repository; @Repository public interface ProductDao extends ElasticsearchRepository<Product, Long>{ }
1.4、索引操作
import com.lun.model.Product; 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.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class SpringDataESIndexTest { //注入 ElasticsearchRestTemplate @Autowired private ElasticsearchRestTemplate elasticsearchRestTemplate; //創建索引并增加映射配置 @Test public void createIndex(){ //創建索引,系統初始化會自動創建索引 System.out.println("創建索引"); } @Test public void deleteIndex(){ //創建索引,系統初始化會自動創建索引 boolean flg = elasticsearchRestTemplate.deleteIndex(Product.class); System.out.println("刪除索引 = " + flg); } }
執行之后可以看到數據實體類 Product 中指定的索引會被自動創建或刪除。
1.5、文檔操作
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.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.test.context.junit4.SpringRunner; import java.util.ArrayList; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class SpringDataESProductDaoTest { @Autowired private ProductDao productDao; /** * 新增 */ @Test public void save(){ Product product = new Product(); product.setId(2L); product.setTitle("華為手機"); product.setCategory("手機"); product.setPrice(2999.0); product.setImages("http://www.atguigu/hw.jpg"); productDao.save(product); } //POSTMAN, GET http://localhost:9200/product/_doc/2 //修改 @Test public void update(){ Product product = new Product(); product.setId(2L); product.setTitle("小米 2 手機"); product.setCategory("手機"); product.setPrice(9999.0); product.setImages("http://www.atguigu/xm.jpg"); productDao.save(product); } //POSTMAN, GET http://localhost:9200/product/_doc/2 //根據 id 查詢 @Test public void findById(){ Product product = productDao.findById(2L).get(); System.out.println(product); } @Test public void findAll(){ Iterable<Product> products = productDao.findAll(); for (Product product : products) { System.out.println(product); } } //刪除 @Test public void delete(){ Product product = new Product(); product.setId(2L); productDao.delete(product); } //POSTMAN, GET http://localhost:9200/product/_doc/2 //批量新增 @Test public void saveAll(){ List<Product> productList = new ArrayList<>(); for (int i = 0; i < 10; i++) { Product product = new Product(); product.setId(Long.valueOf(i)); product.setTitle("["+i+"]小米手機"); product.setCategory("手機"); product.setPrice(1999.0 + i); product.setImages("http://www.atguigu/xm.jpg"); productList.add(product); } productDao.saveAll(productList); } //分頁查詢 @Test public void findByPageable(){ //設置排序(排序方式,正序還是倒序,排序的 id) Sort sort = Sort.by(Sort.Direction.DESC,"id"); int currentPage=0;//當前頁,第一頁從 0 開始, 1 表示第二頁 int pageSize = 5;//每頁顯示多少條 //設置查詢分頁 PageRequest pageRequest = PageRequest.of(currentPage, pageSize,sort); //分頁查詢 Page<Product> productPage = productDao.findAll(pageRequest); for (Product Product : productPage.getContent()) { System.out.println(Product); } } }
上面執行完后結果分別如下:
1)新增 2)修改 3)根據 id 查詢文檔


4)查詢所有文檔 5)批量新增


6)分頁查詢

1.6、文檔搜索
import org.elasticsearch.index.query.MatchQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.TermQueryBuilder; 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.data.domain.PageRequest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class SpringDataESSearchTest { @Autowired private ProductDao productDao; /** * term 查詢 * search(termQueryBuilder) 調用搜索方法,參數查詢構建器對象 */ @Test public void termQuery(){ MatchQueryBuilder termQueryBuilder = QueryBuilders.matchQuery("title", "華為手機"); Iterable<Product> products = productDao.search(termQueryBuilder); for (Product product : products) { System.out.println(product); } } /** * term 查詢加分頁 */ @Test public void termQueryByPage(){ int currentPage= 0 ; int pageSize = 5; //設置查詢分頁 PageRequest pageRequest = PageRequest.of(currentPage, pageSize); MatchQueryBuilder termQueryBuilder = QueryBuilders.matchQuery("title", "華為手機"); Iterable<Product> products = productDao.search(termQueryBuilder,pageRequest); for (Product product : products) { System.out.println(product); } } }
上面執行完后結果分別如下:
- match查詢:

- 分頁查詢:


浙公網安備 33010602011771號