SpringBoot 使用JestClient操作Elasticsearch

1.Jest介紹

SpringBoot 使用JestClient操作Elasticsearch

操作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插件,如下圖所示。

SpringBoot 使用JestClient操作Elasticsearch

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中查詢一致,如圖

SpringBoot 使用JestClient操作Elasticsearch

4.一些建議

相關操作Elasticsearch的客戶端有很多,這裡就不做相關對比了,JestClient本人也在真實上線項目中使用過,這裡只是在使用過幾種的前提下做出幾點建議:

  • Elastic官方已經開始建議使用HTTP方式去操作Elasticsearch了
  • 當初選擇這種的原因是考慮到更好的去擴展版本,封裝響應的操作類可以兼容更多的版本。
  • 在高版本的Elasticsearch中,有一些文檔類型的內容被單獨抽離出來了,比如父子文檔。

領取Java架構師學習視頻,面試資料可私聊,Java,資料,面試


分享到:


相關文章: