当前位置:   article > 正文

Spring Boot入门+深入(十二)-检索ElasticSearch_soringboot 查询elasticsearch数据库

soringboot 查询elasticsearch数据库

目录

一、Spring Boot与检索

 二、ElasticSearch入门

ElasticSearch软件安装

以官网资料为例:

Postman给ElasticSearch发PUT请求

检索GET请求

轻量搜索

使用查询表达式查询

三、Spring Boot与ElasticSearch整合

1.Jest(默认不生效)

Spring Boot 与Jest整合

2.SpringData ElasticSearch

Spring Boot 与SpringData ElasticSearch整合


一、Spring Boot与检索

开源的 ElasticSearch 是目前全文搜索引擎的首选。它可以快速的存储、搜索和分析海量数据。

Elasticsearch是一个分布式搜索服务,提供Restful API,底层基于Lucene,采用多shard(分片)的方式保证数据安全,并且提供自动resharding的功能,github 等大型的站点也是采用了ElasticSearch作为其搜索服务。

员工文档 的形式存储为例:一个文档代表一个员工数据。存储数据到 ElasticSearch 的行为叫做索引 ,但在索引一个文档之前,需要确定将文档存储在哪里。

一个 ElasticSearch 集群可以包含多个索引 ,相应的每个索引可以包含多个类型 。 这些不同的类型存储着多个文档 ,每个文档又有多个属性

ElasticSearch中的概念和数据库有点类似。

        – 索引-----------数据库

        – 类型-----------表

        – 文档-----------表中的记录  文档还可理解为json数据

        – 属性-----------列

Elasticsearch面向文档 的,意味着它存储整个对象或文档。Elasticsearch 不仅存储文档,而且 索引 每个文档的内容,使之可以被检索。在 Elasticsearch 中,我们对文档进行索引、检索、排序和过滤—​而不是对行列数据。这是一种完全不同的思考数据的方式,也是 Elasticsearch 能支持复杂全文检索的原因。

Elasticsearch 使用 JavaScript Object Notation(或者 JSON作为文档的序列化格式。JSON 序列化为大多数编程语言所支持,并且已经成为 NoSQL 领域的标准格式。 它简单、简洁、易于阅读。

如下图理解:

 二、ElasticSearch入门

ElasticSearch软件安装

ElasticSearch环境docker安装:参照Spring Boot入门+深入(六)-Docker

ElasticSearch官网资料学习:Elasticsearch: 权威指南 | Elastic

Postman给ElasticSearch发请求测试:

以官网资料为例:

  1. PUT /megacorp/employee/1
  2. {
  3. "first_name" : "John",
  4. "last_name" : "Smith",
  5. "age" : 25,
  6. "about" : "I love to go rock climbing",
  7. "interests": [ "sports", "music" ]
  8. }
  9. 注意,路径 /megacorp/employee/1 包含了三部分的信息:
  10. megacorp:索引名称
  11. employee:类型名称
  12. 1:特定雇员的ID
  13. PUT /megacorp/employee/2
  14. {
  15. "first_name" : "Jane",
  16. "last_name" : "Smith",
  17. "age" : 32,
  18. "about" : "I like to collect rock albums",
  19. "interests": [ "music" ]
  20. }
  21. PUT /megacorp/employee/3
  22. {
  23. "first_name" : "Douglas",
  24. "last_name" : "Fir",
  25. "age" : 35,
  26. "about": "I like to build cabinets",
  27. "interests": [ "forestry" ]
  28. }

Postman给ElasticSearch发PUT请求

 点击发送后响应结果

 依次把第二条和第三条数据添加进ElasticSearch中

检索GET请求

GET /megacorp/employee/1

将 HTTP 命令由 PUT 改为 GET 可以用来检索文档,同样的,可以使用 DELETE 命令来删除文档,以及使用 HEAD 指令来检查文档是否存在。如果想更新已存在的文档,只需再次 PUT 。

轻量搜索

GET /megacorp/employee/_search

全查:_search

使用查询表达式查询

  1. GET /megacorp/employee/_search
  2. {
  3. "query" : {
  4. "match" : {
  5. "last_name" : "Smith"
  6. }
  7. }
  8. }
  9. Postman中发送POST请求,json中放入查询条件进行查询

更多的功能参照官方文档学习

三、Spring Boot与ElasticSearch整合

创建Spring Boot工程进行整合ElasticSearch测试

SpringBoot默认支持两种技术来和ES交互

spring-boot-autoconfigure-x.x.x.RELEASE.jar下面有ElasticSearch

1.Jest(默认不生效)

需要导入jest的工具包(io.searchbox.client.JestClient)

  1. @Configuration
  2. @ConditionalOnClass(JestClient.class)
  3. @EnableConfigurationProperties(JestProperties.class)
  4. @AutoConfigureAfter(GsonAutoConfiguration.class)
  5. public class JestAutoConfiguration {

JestAutoConfiguration.java生效条件是有JestClient.java

Spring Boot 与Jest整合

pom.xml

  1. <!-- https://mvnrepository.com/artifact/io.searchbox/jest -->
  2. <dependency>
  3. <groupId>io.searchbox</groupId>
  4. <artifactId>jest</artifactId>
  5. <version>5.3.3</version>
  6. </dependency>

application.properties

spring.elasticsearch.jest.uris=http://192.168.0.113:9200

Bean

  1. import io.searchbox.annotations.JestId;
  2. public class Article {
  3. @JestId //标识主键
  4. private Integer id;
  5. private String author;
  6. private String title;
  7. private String content;
  8. public Integer getId() {
  9. return id;
  10. }
  11. public void setId(Integer id) {
  12. this.id = id;
  13. }
  14. public String getAuthor() {
  15. return author;
  16. }
  17. public void setAuthor(String author) {
  18. this.author = author;
  19. }
  20. public String getTitle() {
  21. return title;
  22. }
  23. public void setTitle(String title) {
  24. this.title = title;
  25. }
  26. public String getContent() {
  27. return content;
  28. }
  29. public void setContent(String content) {
  30. this.content = content;
  31. }
  32. }

测试类:

  1. import io.searchbox.client.JestClient;
  2. import io.searchbox.core.Index;
  3. import io.searchbox.core.Search;
  4. import io.searchbox.core.SearchResult;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.boot.test.context.SpringBootTest;
  9. import org.springframework.test.context.junit4.SpringRunner;
  10. import java.io.IOException;
  11. @RunWith(SpringRunner.class)
  12. @SpringBootTest
  13. public class SpringbootElasticApplicationTest {
  14. @Autowired
  15. JestClient jestClient;
  16. @Test
  17. public void test01() {
  18. //1、给Es中索引(保存)一个文档;
  19. Article article = new Article();
  20. article.setId(1);
  21. article.setTitle("一个好消息");
  22. article.setAuthor("张无忌");
  23. article.setContent("Hello World");
  24. //构建一个索引功能
  25. Index index = new Index.Builder(article).index("lwz").type("news").build();
  26. try {
  27. jestClient.execute(index);//执行
  28. } catch (IOException e) {
  29. e.printStackTrace();
  30. }
  31. }
  32. @Test //测试搜索
  33. public void search(){
  34. //查询表达式
  35. String json ="{\n" +
  36. " \"query\" : {\n" +
  37. " \"match\" : {\n" +
  38. " \"content\" : \"hello\"\n" +
  39. " }\n" +
  40. " }\n" +
  41. "}";
  42. //构建搜索功能
  43. Search search = new Search.Builder(json).addIndex("lwz").addType("news").build();
  44. try {
  45. SearchResult result = jestClient.execute(search);//执行
  46. System.out.println(result.getJsonString());
  47. } catch (IOException e) {
  48. e.printStackTrace();
  49. }
  50. }
  51. }

test01()执行后,查询http://192.168.0.113:9200/lwz/news/1

  1. {
  2. "_index": "lwz",
  3. "_type": "news",
  4. "_id": "1",
  5. "_version": 1,
  6. "_seq_no": 0,
  7. "_primary_term": 1,
  8. "found": true,
  9. "_source": {
  10. "id": 1,
  11. "author": "张无忌",
  12. "title": "一个好消息",
  13. "content": "Hello World"
  14. }
  15. }

search()执行检索,控制台打印log结果

{"took":169,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":1,"relation":"eq"},"max_score":0.2876821,"hits":[{"_index":"lwz","_type":"news","_id":"1","_score":0.2876821,"_source":{"id":1,"author":"张无忌","title":"一个好消息","content":"Hello World"}}]}}

2.SpringData ElasticSearch

ElasticsearchAutoConfiguration.java配置了Client 

1.Client 需要配置节点信息clusterNodes;clusterName等

  1. @Configuration
  2. @ConditionalOnClass({ Client.class, TransportClientFactoryBean.class,
  3. NodeClientFactoryBean.class })
  4. @EnableConfigurationProperties(ElasticsearchProperties.class)
  5. public class ElasticsearchAutoConfiguration implements DisposableBean {
  6. ...
  7. @Bean
  8. @ConditionalOnMissingBean
  9. public Client elasticsearchClient() {
  10. try {
  11. return createClient();
  12. }
  13. catch (Exception ex) {
  14. throw new IllegalStateException(ex);
  15. }
  16. }
  17. ...

2.ElasticsearchDataAutoConfiguration.java为我们配置了ElasticsearchTemplate来操作Elasticsearch

  1. @Configuration
  2. @ConditionalOnClass({ Client.class, ElasticsearchTemplate.class })
  3. @AutoConfigureAfter(ElasticsearchAutoConfiguration.class)
  4. public class ElasticsearchDataAutoConfiguration {
  5. @Bean
  6. @ConditionalOnMissingBean
  7. @ConditionalOnBean(Client.class)
  8. public ElasticsearchTemplate elasticsearchTemplate(Client client,
  9. ElasticsearchConverter converter) {
  10. try {
  11. return new ElasticsearchTemplate(client, converter);
  12. }
  13. catch (Exception ex) {
  14. throw new IllegalStateException(ex);
  15. }
  16. }
  17. ....

3.ElasticsearchRepository 类似JPA  自己写接口继承ElasticsearchRepository,来操作Elasticsearch

  1. @Configuration
  2. @ConditionalOnClass({ Client.class, ElasticsearchRepository.class })
  3. @ConditionalOnProperty(prefix = "spring.data.elasticsearch.repositories", name = "enabled", havingValue = "true", matchIfMissing = true)
  4. @ConditionalOnMissingBean(ElasticsearchRepositoryFactoryBean.class)
  5. @Import(ElasticsearchRepositoriesRegistrar.class)
  6. public class ElasticsearchRepositoriesAutoConfiguration {
  7. }

Spring Boot 与SpringData ElasticSearch整合

pom.xml

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  4. </dependency>

application.properties

  1. spring.data.elasticsearch.cluster-name=docker-cluster
  2. spring.data.elasticsearch.cluster-nodes=192.168.0.113:9300

启动Spring Boot项目,验证连接ElasticSearch是否有问题

控制台报错信息:org.elasticsearch.transport.NodeDisconnectedException: [][192.168.0.113:9300][cluster:monitor/nodes/liveness] disconnected

Spring连接Elasticsearch报错:NodeDisconnectedException[[][IP:9300]

什么原因呢?

查看你的Elasticsearch安装目录的logs下的日志.

  1. #查看日志
  2. docker logs 容器ID

日志信息

  1. {"type": "server", "timestamp": "2021-11-28T01:20:25,155Z", "level": "WARN", "component": "o.e.t.TcpTransport", "cluster.name": "docker-cluster", "node.name": "23da5ddf57e3", "message": "exception caught on transport layer [Netty4TcpChannel{localAddress=/172.17.0.3:9300, remoteAddress=/192.168.0.171:52120}], closing connection", "cluster.uuid": "kidKPuQZRLKe2QlYuuOLoQ", "node.id": "v9gf8_LbQjWwCEgEV48buQ" ,
  2. "stacktrace": ["java.lang.IllegalStateException: Received message from unsupported version: [2.0.0] minimal compatible version is: [6.8.0]",
  3. "at org.elasticsearch.transport.InboundDecoder.ensureVersionCompatibility(InboundDecoder.java:210) ~[elasticsearch-7.9.2.jar:7.9.2]",
  4. "at org.elasticsearch.transport.InboundDecoder.readHeader(InboundDecoder.java:177) ~[elasticsearch-7.9.2.jar:7.9.2]",
  5. "at org.elasticsearch.transport.InboundDecoder.internalDecode(InboundDecoder.java:75) ~[elasticsearch-7.9.2.jar:7.9.2]",
  6. "at org.elasticsearch.transport.InboundDecoder.decode(InboundDecoder.java:53) ~[elasticsearch-7.9.2.jar:7.9.2]",
  7. "at org.elasticsearch.transport.InboundPipeline.doHandleBytes(InboundPipeline.java:101) ~[elasticsearch-7.9.2.jar:7.9.2]",
  8. "at org.elasticsearch.transport.InboundPipeline.handleBytes(InboundPipeline.java:82) ~[elasticsearch-7.9.2.jar:7.9.2]",
  9. "at org.elasticsearch.transport.netty4.Netty4MessageChannelHandler.channelRead(Netty4MessageChannelHandler.java:76) ~[transport-netty4-client-7.9.2.jar:7.9.2]",
  10. "at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) [netty-transport-4.1.49.Final.jar:4.1.49.Final]",
  11. "at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) [netty-transport-4.1.49.Final.jar:4.1.49.Final]",
  12. "at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) [netty-transport-4.1.49.Final.jar:4.1.49.Final]",
  13. "at io.netty.handler.logging.LoggingHandler.channelRead(LoggingHandler.java:271) [netty-handler-4.1.49.Final.jar:4.1.49.Final]",
  14. "at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) [netty-transport-4.1.49.Final.jar:4.1.49.Final]",
  15. "at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) [netty-transport-4.1.49.Final.jar:4.1.49.Final]",
  16. "at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) [netty-transport-4.1.49.Final.jar:4.1.49.Final]",
  17. "at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) [netty-transport-4.1.49.Final.jar:4.1.49.Final]",
  18. "at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) [netty-transport-4.1.49.Final.jar:4.1.49.Final]",
  19. "at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) [netty-transport-4.1.49.Final.jar:4.1.49.Final]",
  20. "at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) [netty-transport-4.1.49.Final.jar:4.1.49.Final]",
  21. "at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) [netty-transport-4.1.49.Final.jar:4.1.49.Final]",
  22. "at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714) [netty-transport-4.1.49.Final.jar:4.1.49.Final]",
  23. "at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:615) [netty-transport-4.1.49.Final.jar:4.1.49.Final]",
  24. "at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:578) [netty-transport-4.1.49.Final.jar:4.1.49.Final]",
  25. "at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) [netty-transport-4.1.49.Final.jar:4.1.49.Final]",
  26. "at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) [netty-common-4.1.49.Final.jar:4.1.49.Final]",
  27. "at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) [netty-common-4.1.49.Final.jar:4.1.49.Final]",
  28. "at java.lang.Thread.run(Thread.java:832) [?:?]"] }

其中:Received message from unsupported version: [2.0.0] minimal compatible version is: [6.8.0]",
"at org.elasticsearch.transport.InboundDecoder.ensureVersionCompatibility(InboundDecoder.java:210) ~[elasticsearch-7.9.2.jar:7.9.2]"

从不受支持的版本[2.0.0]接收到的消息最小兼容版本为:[6.8.0],现在我们使用的是elasticsearch-7.9.2。

结论:低版本ja包的不支持高版本的Elasticsearch

【ES版本有可能不合适】涉及到版本匹配的问题?

在Spring官网,找到Spring Data模块,找到Spring Data ElasticSearch,点击Reference Doc,

Project Metadata Version Control https://github.com/spring-projects/spring-data-elasticsearch

点击连接往下翻,找到The compatibility between Spring Data Elasticsearch, Elasticsearch client drivers and Spring Boot versions can be found in the reference documentation.

点击reference documentation,连接到 版本匹配关系表。

 解决方式:调整自己项目版本。

 如果版本不适配:
        1)、升级SpringBoot版本
        2)、安装对应版本的ES

调整完版本匹配,继续进行整合测试。

启动SpringBoot,后台打印日志adding transport node : 192.168.0.113:9300

说明连接上ElasticSearch。

控制台显示错误:

[Shroud] node {#transport#-1}{192.168.0.113}{192.168.0.113:9300} not part of the cluster Cluster [docker-cluster], ignoring...

说明:application.properties中的spring.data.elasticsearch.cluster-name=docker-cluster

cluster-name配置错误。

Bean

  1. import org.springframework.data.elasticsearch.annotations.Document;
  2. @Document(indexName = "lwz",type = "book")
  3. public class Book {
  4. private Integer id;
  5. private String bookName;
  6. private String author;
  7. public Integer getId() {
  8. return id;
  9. }
  10. public void setId(Integer id) {
  11. this.id = id;
  12. }
  13. public String getBookName() {
  14. return bookName;
  15. }
  16. public void setBookName(String bookName) {
  17. this.bookName = bookName;
  18. }
  19. public String getAuthor() {
  20. return author;
  21. }
  22. public void setAuthor(String author) {
  23. this.author = author;
  24. }
  25. @Override
  26. public String toString() {
  27. return "Book{" +
  28. "id=" + id +
  29. ", bookName='" + bookName + '\'' +
  30. ", author='" + author + '\'' +
  31. '}';
  32. }
  33. }

Repository

  1. import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
  2. import java.util.List;
  3. public interface BookRepository extends ElasticsearchRepository<Book,Integer> {
  4. public List<Book> findByBookNameLike(String bookName);//自定义查询方法
  5. }

测试类:

  1. import org.junit.Test;
  2. import org.junit.runner.RunWith;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.boot.test.context.SpringBootTest;
  5. import org.springframework.test.context.junit4.SpringRunner;
  6. @RunWith(SpringRunner.class)
  7. @SpringBootTest
  8. public class SpringbootElasticApplicationTest1 {
  9. @Autowired
  10. BookRepository bookRepository;
  11. @Test
  12. public void test01(){
  13. Book book = new Book();
  14. book.setId(1);
  15. book.setBookName("西游记");
  16. book.setAuthor("吴承恩");
  17. bookRepository.index(book);
  18. }
  19. @Test
  20. public void test02(){
  21. for (Book book : bookRepository.findByBookNameLike("游")) {
  22. System.out.println(book);
  23. };
  24. }
  25. }

test01()插入ES数据---->类似于JPA插入数据库数据

test02()查询ES数据---->类似于JPA查询数据库数据

test02()查询结果:Book{id=1, bookName='西游记', author='吴承恩'}

Spring Boot入门+深入(一):Spring Boot入门+深入(一)

Spring Boot入门+深入(十三):Spring Boot入门+深入(十三)-任务

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/566593
推荐阅读
相关标签
  

闽ICP备14008679号