1.Jest介紹
操作Elasticsearch的客戶端有很多,SpringBoot也提供了方式去操作,這裡介紹另外一種方式去使用Elasticsearch --- JestClient
JestClient是一款基於HTTP方式操作的Elasticsearch的客戶端,支持同步和異步操作,同時也可以結合ElasticSearch的依賴進行操作Elasticsearch。
支持多個版本的Elasticsearch,如下:
Jest VersionElasticsearch Version>= 6.0.06>= 5.0.05>= 2.0.020.1.0 - 1.0.01<= 0.0.6< 1
更多信息可以查看github,地址是:https://github.com/searchbox-io/Jest
2.SpringBoot整合JestClient
接下來介紹如何在SpringBoot中使用JestClient操作Elasticsearch。
2.1 前置工作
首先啟動Elasticsearch,我這裡是在本地啟動的Elasticsearch,版本是6.8.2,為了方便查看數據,這裡使用Elasticsearch-Head插件,如下圖所示。
2.2 添加Jest依賴
創建項目,在pom文件中加入Jest依賴(這裡根據上面版本對應添加依賴),這裡額外添加量了elasticsearch和lombok為了方便操作,如下:
<code>
<project> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelversion>4.0.0/<modelversion>
<groupid>com.dalaoyang/<groupid>
<artifactid>springboot_jestclient/<artifactid>
<version>0.0.1-SNAPSHOT/<version>
<name>springboot_jestclient/<name>
<description>springboot_jestclient/<description>
<properties>
<java.version>1.8/<java.version>
<project.build.sourceencoding>UTF-8/<project.build.sourceencoding>
<project.reporting.outputencoding>UTF-8/<project.reporting.outputencoding>
<spring-boot.version>2.2.6.RELEASE/<spring-boot.version>
/<properties>
<dependencies>
<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>
<exclusions>
<exclusion>
<groupid>org.junit.vintage/<groupid>
<artifactid>junit-vintage-engine/<artifactid>
/<exclusion>
/<exclusions>
/<dependency>
<dependency>
<groupid>io.searchbox/<groupid>
<artifactid>jest/<artifactid>
<version>6.3.1/<version>
/<dependency>
<dependency>
<groupid>org.projectlombok/<groupid>
<artifactid>lombok/<artifactid>
<version>1.16.10/<version>
/<dependency>
<dependency>
<groupid>org.elasticsearch/<groupid>
<artifactid>elasticsearch/<artifactid>
<version>6.8.2/<version>
/<dependency>
/<dependencies>
<dependencymanagement>
<dependencies>
<dependency>
<groupid>org.springframework.boot/<groupid>
<artifactid>spring-boot-dependencies/<artifactid>
<version>${spring-boot.version}/<version>
<type>pom/<type>
<scope>import/<scope>
/<dependency>
/<dependencies>
/<dependencymanagement>
<build>
<plugins>
<plugin>
<groupid>org.apache.maven.plugins/<groupid>
<artifactid>maven-compiler-plugin/<artifactid>
<configuration>
<source>1.8/<source>
<target>1.8/<target>
<encoding>UTF-8/<encoding>
/<configuration>
/<plugin>
<plugin>
<groupid>org.springframework.boot/<groupid>
<artifactid>spring-boot-maven-plugin/<artifactid>
<version>2.2.6.RELEASE/<version>
/<plugin>
/<plugins>
/<build>
/<project>
/<code>
2.3 配置文件
在配置文件中添加elasticsearch相關配置,其中uris配置Elasticsearch的HTTP端口,如本文添加的配置:
<code>spring.application.name=springboot_jestclient
# 應用服務web訪問端口
server.port=8888
spring.elasticsearch.rest.uris=http://localhost:9200
spring.elasticsearch.jest.username=elastic
spring.elasticsearch.jest.password=elastic
/<code>
到這裡其實已經整合完成了,是不是非常簡單?
3.Elasticsearch基本操作
接下介紹如何操作Elasticsearch,這裡分別介紹如下幾部分內容:
- 索引文檔
- 索引類操作
- 文檔類操作
- 查詢操作
3.1 文檔實體
這裡創建一個Book文檔做為示例,其中@JestId為文檔id,即Elasticsearch中的_id字段,本文BookDocument內容如下:
<code>package com.dalaoyang.document;
import io.searchbox.annotations.JestId;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class BookDocument {
@JestId
private String id;
private String bookName;
private String bookAuthor;
private Integer pages;
private String desc;
}
/<code>
為了方便操作,這裡創建了一個request對象進行操作,如下:
<code>package com.dalaoyang.model;
import com.dalaoyang.document.BookDocument;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class BookRequest {
//刪除文檔用
private String id;
//查詢用
private String keyword;
private String indexName;
private String typeName;
//新增文檔用
private BookDocument body;
}
/<code>
在使用相關操作時,其實都是通過io.searchbox.client.JestClient#execute來進行操作(需要注意,這裡沒有對JestClient進行配置,只是使用的默認的配置),將對應動作當做參數傳入,接下來介紹幾個常用的動作。
3.2 索引類操作
結合MySQL來看的話,索引可以理解為一個數據庫,索引相關的操作可能不是很多,這裡介紹相對比較常用的是創建索引和刪除索引,如下:
3.2.1 創建索引
<code>CreateIndex createIndex = new CreateIndex.Builder(indexName).build();
/<code>
3.2.2 刪除索引
<code>DeleteIndex deleteIndex = new DeleteIndex.Builder(indexName).build();
/<code>
通過上面兩個操作可以看到,都是通過使用對應的Index實體來操作對應實體,當然還有一些不是很常用的,如果有需要可以查看相關文檔進行使用,這裡不一一介紹了,完整s示例內容如下:
<code>package com.dalaoyang.web;
import io.searchbox.client.JestClient;
import io.searchbox.client.JestResult;
import io.searchbox.indices.CreateIndex;
import io.searchbox.indices.DeleteIndex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class IndexController {
@Autowired
private JestClient jestClient;
@GetMapping("createIndex")
public String createIndex(String indexName) throws Exception{
CreateIndex createIndex = new CreateIndex.Builder(indexName).build();
JestResult result = jestClient.execute(createIndex);
return result.getJsonString();
}
@GetMapping("deleteIndex")
public String deleteIndex(String indexName) throws Exception{
DeleteIndex deleteIndex = new DeleteIndex.Builder(indexName).build();
JestResult result = jestClient.execute(deleteIndex);
return result.getJsonString();
}
}
/<code>
3.3 文檔類操作
文檔相當於MySQL中的行記錄,也就是說一條數據,由於新增和修改在同一個方法內,所以這裡也是對新增(和修改)和刪除方法進行介紹,如下:
3.3.1 新增或修改文檔
首先會判斷索引是否存在,不存在的話會根據索引文檔進行創建索引,然後進行新增或修改操作,如果沒有指定id的話(上文說的註解@JestId字段),會自動生成一個id。
<code>Index.Builder builder = new Index.Builder(bookRequest.getBody());
Index index = builder.index(bookRequest.getIndexName()).type(bookRequest.getTypeName()).build();
/<code>
這裡使用新增文檔創建三條數據方便後面查詢,如下:
<code>{
"indexName": "book",
"typeName": "book",
"body": {"id":"test0001","bookName":"數學書","bookAuthor":"復旦大學","pages":100,"desc":"復旦大學的數學書"}
}
/<code>
<code>{
"indexName": "book",
"typeName": "book",
"body": {"id":"test0003","bookName":"語文書","bookAuthor":"北京大學","pages":100,"desc":"北京大學的語文書"}
}
/<code>
<code>{
"indexName": "book",
"typeName": "book",
"body": {"id":"test0003","bookName":"英文書","bookAuthor":"清華大學","pages":200,"desc":"清華大學的英文書"}
}
/<code>
3.3.2 刪除文檔(根據id)
<code>Delete index = new Delete.Builder(bookRequest.getId()).index(bookRequest.getIndexName()).type(bookRequest.getTypeName()).build();
/<code>
完整示例內容如下:
<code>package com.dalaoyang.web;
import com.dalaoyang.model.BookRequest;
import io.searchbox.client.JestClient;
import io.searchbox.client.JestResult;
import io.searchbox.core.Delete;
import io.searchbox.core.Index;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DocumentController {
@Autowired
private JestClient jestClient;
@PostMapping("saveOrUpdateDocument")
public String saveOrUpdateDocument(@RequestBody BookRequest bookRequest) throws Exception{
Index.Builder builder = new Index.Builder(bookRequest.getBody());
Index index = builder.index(bookRequest.getIndexName()).type(bookRequest.getTypeName()).build();
JestResult result = jestClient.execute(index);
return result.getJsonString();
}
@PostMapping("deleteDocumentById")
public String deleteDocumentById(@RequestBody BookRequest bookRequest) throws Exception{
Delete index = new Delete.Builder(bookRequest.getId()).index(bookRequest.getIndexName()).type(bookRequest.getTypeName()).build();
JestResult result = jestClient.execute(index);
return result.getJsonString();
}
}
/<code>
3.4 查詢操作
查詢操作可能是對Elasticsearch最需要使用的場景,這裡舉一個簡單的場景,輸入關鍵字,查詢對應book文檔,關鍵字匹配(bookName,bookAuthor,desc)三個字段,這裡結合Elasticsearch官方依賴進行操作,完整示例如下:
<code>
package com.dalaoyang.web;
import com.dalaoyang.model.BookRequest;
import io.searchbox.client.JestClient;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class QueryController {
@Autowired
private JestClient jestClient;
@PostMapping("search")
public String search(@RequestBody BookRequest bookRequest) throws Exception{
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(new MultiMatchQueryBuilder(bookRequest.getKeyword(), "bookName","bookAuthor","desc"));
log.info(searchSourceBuilder.toString());
SearchResult result = jestClient.execute(new Search.Builder(searchSourceBuilder.toString())
.addIndex(bookRequest.getIndexName())
.addType(bookRequest.getTypeName())
.build());
return result.getJsonString();
}
}
/<code>
比如這裡搜索清華,這裡我打印了一下查詢語句,如下:
<code>{
"query":{
"multi_match":{
"query":"清華",
"fields":[
"bookAuthor^1.0",
"bookName^1.0",
"desc^1.0"
],
"type":"best_fields",
"operator":"OR",
"slop":0,
"prefix_length":0,
"max_expansions":50,
"zero_terms_query":"NONE",
"auto_generate_synonyms_phrase_query":true,
"fuzzy_transpositions":true,
"boost":1
}
}
}
/<code>
查詢的結構只有一條,與在Elasticsearch-Head中查詢一致,如圖
4.一些建議
相關操作Elasticsearch的客戶端有很多,這裡就不做相關對比了,JestClient本人也在真實上線項目中使用過,這裡只是在使用過幾種的前提下做出幾點建議:
- Elastic官方已經開始建議使用HTTP方式去操作Elasticsearch了
- 當初選擇這種的原因是考慮到更好的去擴展版本,封裝響應的操作類可以兼容更多的版本。
- 在高版本的Elasticsearch中,有一些文檔類型的內容被單獨抽離出來了,比如父子文檔。
領取Java架構師學習視頻,面試資料可私聊,Java,資料,面試
閱讀更多 程序員諸葛 的文章