暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

SpringBoot 使用JestClient操作Elasticsearch

dalaoyang 2020-05-03
432

1.Jest介绍

操作Elasticsearch的客户端有很多,SpringBoot也提供了方式去操作,这里介绍另外一种方式去使用Elasticsearch --- JestClient

JestClient是一款基于HTTP方式操作的Elasticsearch的客户端,支持同步和异步操作,同时也可以结合ElasticSearch的依赖进行操作Elasticsearch。

支持多个版本的Elasticsearch,如下:

Jest VersionElasticsearch Version

= 6.0.0 | 6 = 5.0.0 | 5 = 2.0.0 | 2 0.1.0 - 1.0.0 | 1 <= 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为了方便操作,如下:

  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

  4. <modelVersion>4.0.0</modelVersion>

  5. <groupId>com.dalaoyang</groupId>

  6. <artifactId>springboot_jestclient</artifactId>

  7. <version>0.0.1-SNAPSHOT</version>

  8. <name>springboot_jestclient</name>

  9. <description>springboot_jestclient</description>


  10. <properties>

  11. <java.version>1.8</java.version>

  12. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

  13. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

  14. <spring-boot.version>2.2.6.RELEASE</spring-boot.version>

  15. </properties>


  16. <dependencies>

  17. <dependency>

  18. <groupId>org.springframework.boot</groupId>

  19. <artifactId>spring-boot-starter-web</artifactId>

  20. </dependency>


  21. <dependency>

  22. <groupId>org.springframework.boot</groupId>

  23. <artifactId>spring-boot-starter-test</artifactId>

  24. <scope>test</scope>

  25. <exclusions>

  26. <exclusion>

  27. <groupId>org.junit.vintage</groupId>

  28. <artifactId>junit-vintage-engine</artifactId>

  29. </exclusion>

  30. </exclusions>

  31. </dependency>


  32. <dependency>

  33. <groupId>io.searchbox</groupId>

  34. <artifactId>jest</artifactId>

  35. <version>6.3.1</version>

  36. </dependency>


  37. <dependency>

  38. <groupId>org.projectlombok</groupId>

  39. <artifactId>lombok</artifactId>

  40. <version>1.16.10</version>

  41. </dependency>


  42. <dependency>

  43. <groupId>org.elasticsearch</groupId>

  44. <artifactId>elasticsearch</artifactId>

  45. <version>6.8.2</version>

  46. </dependency>

  47. </dependencies>


  48. <dependencyManagement>

  49. <dependencies>

  50. <dependency>

  51. <groupId>org.springframework.boot</groupId>

  52. <artifactId>spring-boot-dependencies</artifactId>

  53. <version>${spring-boot.version}</version>

  54. <type>pom</type>

  55. <scope>import</scope>

  56. </dependency>

  57. </dependencies>

  58. </dependencyManagement>


  59. <build>

  60. <plugins>

  61. <plugin>

  62. <groupId>org.apache.maven.plugins</groupId>

  63. <artifactId>maven-compiler-plugin</artifactId>

  64. <configuration>

  65. <source>1.8</source>

  66. <target>1.8</target>

  67. <encoding>UTF-8</encoding>

  68. </configuration>

  69. </plugin>

  70. <plugin>

  71. <groupId>org.springframework.boot</groupId>

  72. <artifactId>spring-boot-maven-plugin</artifactId>

  73. <version>2.2.6.RELEASE</version>

  74. </plugin>

  75. </plugins>

  76. </build>


  77. </project>

复制

2.3 配置文件

在配置文件中添加elasticsearch相关配置,其中uris配置Elasticsearch的HTTP端口,如本文添加的配置:

  1. spring.application.name=springboot_jestclient

  2. # 应用服务web访问端口

  3. server.port=8888


  4. spring.elasticsearch.rest.uris=http://localhost:9200

  5. spring.elasticsearch.jest.username=elastic

  6. spring.elasticsearch.jest.password=elastic

复制

到这里其实已经整合完成了,是不是非常简单?

3.Elasticsearch基本操作

接下介绍如何操作Elasticsearch,这里分别介绍如下几部分内容:

  • 索引文档

  • 索引类操作

  • 文档类操作

  • 查询操作

3.1 文档实体

这里创建一个Book文档做为示例,其中@JestId为文档id,即Elasticsearch中的_id字段,本文BookDocument内容如下:

  1. package com.dalaoyang.document;


  2. import io.searchbox.annotations.JestId;

  3. import lombok.AllArgsConstructor;

  4. import lombok.Builder;

  5. import lombok.Data;

  6. import lombok.NoArgsConstructor;


  7. @Data

  8. @Builder

  9. @AllArgsConstructor

  10. @NoArgsConstructor

  11. public class BookDocument {


  12. @JestId

  13. private String id;

  14. private String bookName;

  15. private String bookAuthor;

  16. private Integer pages;

  17. private String desc;

  18. }

复制

为了方便操作,这里创建了一个request对象进行操作,如下:

  1. package com.dalaoyang.model;


  2. import com.dalaoyang.document.BookDocument;

  3. import lombok.AllArgsConstructor;

  4. import lombok.Builder;

  5. import lombok.Data;

  6. import lombok.NoArgsConstructor;


  7. @Data

  8. @Builder

  9. @AllArgsConstructor

  10. @NoArgsConstructor

  11. public class BookRequest {


  12. //删除文档用

  13. private String id;

  14. //查询用

  15. private String keyword;

  16. private String indexName;

  17. private String typeName;

  18. //新增文档用

  19. private BookDocument body;

  20. }

复制

在使用相关操作时,其实都是通过io.searchbox.client.JestClient#execute来进行操作(需要注意,这里没有对JestClient进行配置,只是使用的默认的配置),将对应动作当做参数传入,接下来介绍几个常用的动作。

3.2 索引类操作

结合MySQL来看的话,索引可以理解为一个数据库,索引相关的操作可能不是很多,这里介绍相对比较常用的是创建索引和删除索引,如下:

3.2.1 创建索引

  1. CreateIndex createIndex = new CreateIndex.Builder(indexName).build();

复制

3.2.2 删除索引

  1. DeleteIndex deleteIndex = new DeleteIndex.Builder(indexName).build();

复制

通过上面两个操作可以看到,都是通过使用对应的Index实体来操作对应实体,当然还有一些不是很常用的,如果有需要可以查看相关文档进行使用,这里不一一介绍了,完整s示例内容如下:

  1. package com.dalaoyang.web;


  2. import io.searchbox.client.JestClient;

  3. import io.searchbox.client.JestResult;

  4. import io.searchbox.indices.CreateIndex;

  5. import io.searchbox.indices.DeleteIndex;

  6. import org.springframework.beans.factory.annotation.Autowired;

  7. import org.springframework.web.bind.annotation.GetMapping;

  8. import org.springframework.web.bind.annotation.RestController;


  9. @RestController

  10. public class IndexController {


  11. @Autowired

  12. private JestClient jestClient;


  13. @GetMapping("createIndex")

  14. public String createIndex(String indexName) throws Exception{

  15. CreateIndex createIndex = new CreateIndex.Builder(indexName).build();

  16. JestResult result = jestClient.execute(createIndex);

  17. return result.getJsonString();

  18. }


  19. @GetMapping("deleteIndex")

  20. public String deleteIndex(String indexName) throws Exception{

  21. DeleteIndex deleteIndex = new DeleteIndex.Builder(indexName).build();

  22. JestResult result = jestClient.execute(deleteIndex);

  23. return result.getJsonString();

  24. }

  25. }

复制

3.3 文档类操作

文档相当于MySQL中的行记录,也就是说一条数据,由于新增和修改在同一个方法内,所以这里也是对新增(和修改)和删除方法进行介绍,如下:

3.3.1 新增或修改文档

首先会判断索引是否存在,不存在的话会根据索引文档进行创建索引,然后进行新增或修改操作,如果没有指定id的话(上文说的注解@JestId字段),会自动生成一个id。

  1. Index.Builder builder = new Index.Builder(bookRequest.getBody());

  2. Index index = builder.index(bookRequest.getIndexName()).type(bookRequest.getTypeName()).build();

复制

这里使用新增文档创建三条数据方便后面查询,如下:

  1. {

  2. "indexName": "book",

  3. "typeName": "book",

  4. "body": {"id":"test0001","bookName":"数学书","bookAuthor":"复旦大学","pages":100,"desc":"复旦大学的数学书"}

  5. }

复制
  1. {

  2. "indexName": "book",

  3. "typeName": "book",

  4. "body": {"id":"test0003","bookName":"语文书","bookAuthor":"北京大学","pages":100,"desc":"北京大学的语文书"}

  5. }

复制
  1. {

  2. "indexName": "book",

  3. "typeName": "book",

  4. "body": {"id":"test0003","bookName":"英文书","bookAuthor":"清华大学","pages":200,"desc":"清华大学的英文书"}

  5. }

复制

3.3.2 删除文档(根据id)

  1. Delete index = new Delete.Builder(bookRequest.getId()).index(bookRequest.getIndexName()).type(bookRequest.getTypeName()).build();

复制

完整示例内容如下:

  1. package com.dalaoyang.web;


  2. import com.dalaoyang.model.BookRequest;

  3. import io.searchbox.client.JestClient;

  4. import io.searchbox.client.JestResult;

  5. import io.searchbox.core.Delete;

  6. import io.searchbox.core.Index;

  7. import org.springframework.beans.factory.annotation.Autowired;

  8. import org.springframework.web.bind.annotation.PostMapping;

  9. import org.springframework.web.bind.annotation.RequestBody;

  10. import org.springframework.web.bind.annotation.RestController;



  11. @RestController

  12. public class DocumentController {


  13. @Autowired

  14. private JestClient jestClient;


  15. @PostMapping("saveOrUpdateDocument")

  16. public String saveOrUpdateDocument(@RequestBody BookRequest bookRequest) throws Exception{

  17. Index.Builder builder = new Index.Builder(bookRequest.getBody());

  18. Index index = builder.index(bookRequest.getIndexName()).type(bookRequest.getTypeName()).build();

  19. JestResult result = jestClient.execute(index);

  20. return result.getJsonString();

  21. }


  22. @PostMapping("deleteDocumentById")

  23. public String deleteDocumentById(@RequestBody BookRequest bookRequest) throws Exception{

  24. Delete index = new Delete.Builder(bookRequest.getId()).index(bookRequest.getIndexName()).type(bookRequest.getTypeName()).build();

  25. JestResult result = jestClient.execute(index);

  26. return result.getJsonString();

  27. }

  28. }

复制

3.4 查询操作

查询操作可能是对Elasticsearch最需要使用的场景,这里举一个简单的场景,输入关键字,查询对应book文档,关键字匹配(bookName,bookAuthor,desc)三个字段,这里结合Elasticsearch官方依赖进行操作,完整示例如下:

  1. package com.dalaoyang.web;


  2. import com.dalaoyang.model.BookRequest;

  3. import io.searchbox.client.JestClient;

  4. import io.searchbox.core.Search;

  5. import io.searchbox.core.SearchResult;

  6. import lombok.extern.slf4j.Slf4j;

  7. import org.elasticsearch.index.query.MultiMatchQueryBuilder;

  8. import org.elasticsearch.search.builder.SearchSourceBuilder;

  9. import org.springframework.beans.factory.annotation.Autowired;

  10. import org.springframework.web.bind.annotation.PostMapping;

  11. import org.springframework.web.bind.annotation.RequestBody;

  12. import org.springframework.web.bind.annotation.RestController;


  13. @RestController

  14. @Slf4j

  15. public class QueryController {


  16. @Autowired

  17. private JestClient jestClient;


  18. @PostMapping("search")

  19. public String search(@RequestBody BookRequest bookRequest) throws Exception{

  20. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

  21. searchSourceBuilder.query(new MultiMatchQueryBuilder(bookRequest.getKeyword(), "bookName","bookAuthor","desc"));

  22. log.info(searchSourceBuilder.toString());

  23. SearchResult result = jestClient.execute(new Search.Builder(searchSourceBuilder.toString())

  24. .addIndex(bookRequest.getIndexName())

  25. .addType(bookRequest.getTypeName())

  26. .build());

  27. return result.getJsonString();

  28. }

  29. }

复制

比如这里搜索清华,这里我打印了一下查询语句,如下:

  1. {

  2. "query":{

  3. "multi_match":{

  4. "query":"清华",

  5. "fields":[

  6. "bookAuthor^1.0",

  7. "bookName^1.0",

  8. "desc^1.0"

  9. ],

  10. "type":"best_fields",

  11. "operator":"OR",

  12. "slop":0,

  13. "prefix_length":0,

  14. "max_expansions":50,

  15. "zero_terms_query":"NONE",

  16. "auto_generate_synonyms_phrase_query":true,

  17. "fuzzy_transpositions":true,

  18. "boost":1

  19. }

  20. }

  21. }

复制

查询的结构只有一条,与在Elasticsearch-Head中查询一致,如图

4.一些建议

相关操作Elasticsearch的客户端有很多,这里就不做相关对比了,JestClient本人也在真实上线项目中使用过,这里只是在使用过几种的前提下做出几点建议:

  • Elastic官方已经开始建议使用HTTP方式去操作Elasticsearch了

  • 当初选择这种的原因是考虑到更好的去扩展版本,封装响应的操作类可以兼容更多的版本。

  • 在高版本的Elasticsearch中,有一些文档类型的内容被单独抽离出来了,比如父子文档。

5.源码

源码地址:https://gitee.com/dalaoyang/springbootlearn/tree/master/springbootjestclient


-END-


文章转载自dalaoyang,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论