Spring Boot整合elasticsearch的详细步骤

时间:2022-09-28 12:59:17

一、简介

我们的应用经常需要添加检索功能,开源的 elasticsearch 是目前全文搜索引擎的 首选。他可以快速的存储、搜索和分析海量数据。spring boot通过整合spring data elasticsearch为我们提供了非常便捷的检索功能支持;

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

我们建立一个网站或应用程序,并要添加搜索功能,但是想要完成搜索工作的创建是非常困难的。我们希望搜索解决方案要运行速度快,我们希望能有一个零配置和一个完全免费的搜索模式,我们希望能够简单地使用json通过http来索引数据,我们希望我们的搜索服务器始终可用,我们希望能够从一台开始并扩展到数百台,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。因此我们利用elasticsearch来解决所有这些问题及可能出现的更多其它问题。

二、安装elasticsearch

我们采用 docker镜像安装的方式。

?
1
2
3
4
5
#下载镜像
docker pull elasticsearch
#启动镜像,elasticsearch 启动是会默认分配2g的内存 ,我们启动是设置小一点,防止我们内存不够启动失败
#9200是elasticsearch 默认的web通信接口,9300是分布式情况下,elasticsearch个节点通信的端口
docker run -e es_java_opts="-xms256m -xmx256m" -d -p 9200:9200 -p 9300:9300 --name es01 5c1e1ecfe33a

访问 127.0.0.1:9200 如下图,说明安装成功

三、elasticsearch的一些概念

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

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

类似关系:

  • 索引-数据库
  • 类型-表
  • 文档-表中的记录 – 属性-列

elasticsearch使用可以参早官方文档,在这里不在讲解。

四、整合 elasticsearch

创建项目 springboot-elasticsearch,引入web支持

springboot 提供了两种方式操作elasticsearch,jest 和 springdata。

jest 操作 elasticsearch

jest是elasticsearch的java http rest客户端。

elasticsearch已经有一个java api,elasticsearch也在内部使用它,但是jest填补了空白,它是elasticsearch http rest接口缺少的客户端。

1. pom.xml

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?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>
 
  <groupid>com.gf</groupid>
  <artifactid>springboot-elasticsearch</artifactid>
  <version>0.0.1-snapshot</version>
  <packaging>jar</packaging>
 
  <name>springboot-elasticsearch</name>
  <description>demo project for spring boot</description>
 
  <parent>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-parent</artifactid>
    <version>2.1.1.release</version>
    <relativepath/> <!-- lookup parent from repository -->
  </parent>
 
  <properties>
    <project.build.sourceencoding>utf-8</project.build.sourceencoding>
    <project.reporting.outputencoding>utf-8</project.reporting.outputencoding>
    <java.version>1.8</java.version>
  </properties>
 
  <dependencies>
    <dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-data-elasticsearch</artifactid>
  </dependency>
    <dependency>
      <groupid>io.searchbox</groupid>
      <artifactid>jest</artifactid>
      <version>5.3.3</version>
    </dependency>
 
    <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>
    </dependency>
  </dependencies>
 
  <build>
    <plugins>
      <plugin>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-maven-plugin</artifactid>
      </plugin>
    </plugins>
  </build>
</project>

2. application.properties

?
1
spring.elasticsearch.jest.uris=http://127.0.0.1:9200

3. article

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.gf.entity;
import io.searchbox.annotations.jestid;
public class article {
 
  @jestid
  private integer id;
  private string author;
  private string title;
  private string content;
 
  public integer getid() {
    return id;
  }
 
  public void setid(integer id) {
    this.id = id;
  }
 
  public string getauthor() {
    return author;
  }
 
  public void setauthor(string author) {
    this.author = author;
  }
 
  public string gettitle() {
    return title;
  }
 
  public void settitle(string title) {
    this.title = title;
  }
 
  public string getcontent() {
    return content;
  }
 
  public void setcontent(string content) {
    this.content = content;
  }
 
  @override
  public string tostring() {
    final stringbuilder sb = new stringbuilder( "{\"article\":{" );
    sb.append( "\"id\":" )
        .append( id );
    sb.append( ",\"author\":\"" )
        .append( author ).append( '\"' );
    sb.append( ",\"title\":\"" )
        .append( title ).append( '\"' );
    sb.append( ",\"content\":\"" )
        .append( content ).append( '\"' );
    sb.append( "}}" );
    return sb.tostring();
  }
}

4. springboot测试类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.gf;
 
import com.gf.entity.article;
import io.searchbox.client.jestclient;
import io.searchbox.core.index;
import io.searchbox.core.search;
import io.searchbox.core.searchresult;
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.test.context.junit4.springrunner;
 
import java.io.ioexception;
 
@runwith(springrunner.class)
@springboottest
public class springbootelasticsearchapplicationtests {
 
  @autowired
  jestclient jestclient;
 
  @test
  public void createindex() {
    //1. 给es中索引(保存)一个文档
    article article = new article();
    article.setid( 1 );
    article.settitle( "好消息" );
    article.setauthor( "张三" );
    article.setcontent( "hello world" );
 
    //2. 构建一个索引
    index index = new index.builder( article ).index( "gf" ).type( "news" ).build();
    try {
      //3. 执行
      jestclient.execute( index );
    } catch (ioexception e) {
      e.printstacktrace();
    }
  }
 
  @test
  public void search() {
    //查询表达式
    string query = "{\n" +
        "  \"query\" : {\n" +
        "    \"match\" : {\n" +
        "      \"content\" : \"hello\"\n" +
        "    }\n" +
        "  }\n" +
        "}";
 
    //构建搜索功能
    search search = new search.builder( query ).addindex( "gf" ).addtype( "news" ).build();
 
    try {
      //执行
      searchresult result = jestclient.execute( search );
      system.out.println(result.getjsonstring());
    } catch (ioexception e) {
      e.printstacktrace();
    }
  }
}

jest的更多api ,可以参照github的文档:https://github.com/searchbox-io/jest

springdata 操作 elasticsearch

1. application.properties

?
1
2
spring.data.elasticsearch.cluster-name=elasticsearch
spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300

2. book

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.gf.entity;
@document( indexname = "gf" , type = "book")
public class book {
  private integer id;
  private string bookname;
  private string author;
 
  public integer getid() {
    return id;
  }
 
  public void setid(integer id) {
    this.id = id;
  }
 
  public string getbookname() {
    return bookname;
  }
 
  public void setbookname(string bookname) {
    this.bookname = bookname;
  }
 
  public string getauthor() {
    return author;
  }
 
  public void setauthor(string author) {
    this.author = author;
  }
 
  @override
  public string tostring() {
    final stringbuilder sb = new stringbuilder( "{\"book\":{" );
    sb.append( "\"id\":" )
        .append( id );
    sb.append( ",\"bookname\":\"" )
        .append( bookname ).append( '\"' );
    sb.append( ",\"author\":\"" )
        .append( author ).append( '\"' );
    sb.append( "}}" );
    return sb.tostring();
  
}

3. bookrepository

?
1
2
3
4
5
6
7
8
9
10
package com.gf.repository;
import com.gf.entity.book;
import org.springframework.data.elasticsearch.repository.elasticsearchrepository;
 
import java.util.list;
 
public interface bookrepository extends elasticsearchrepository<book, integer>{
 
  list<book> findbybooknamelike(string bookname);
}

4. springboot 测试类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.gf;
import com.gf.entity.article;
import com.gf.entity.book;
import com.gf.repository.bookrepository;
import io.searchbox.client.jestclient;
import io.searchbox.core.index;
import io.searchbox.core.search;
import io.searchbox.core.searchresult;
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.test.context.junit4.springrunner;
import java.io.ioexception;
import java.util.list;
 
@runwith(springrunner.class)
@springboottest
public class springbootelasticsearchapplicationtests {
  @autowired
  bookrepository bookrepository;
  
  @test
  public void createindex2(){
    book book = new book();
    book.setid(1);
    book.setbookname("西游记");
    book.setauthor( "吴承恩" );
    bookrepository.index( book );
  }
 
  @test
  public void usefind() {
    list<book> list = bookrepository.findbybooknamelike( "游" );
    for (book book : list) {
      system.out.println(book);
    }
  }
}

我们启动测试 ,发现报错 。

这个报错的原因是springdata的版本与我elasticsearch的版本有冲突,下午是springdata官方文档给出的适配表。

我们使用的springdata elasticsearch的 版本是3.1.3 ,对应的版本应该是6.2.2版本,而我们是的 elasticsearch 是 5.6.9,所以目前我们需要更换elasticsearch的版本为6.x

?
1
2
docker pull elasticsearch:6.5.1
docker run -e es_java_opts="-xms256m -xmx256m" -d -p 9200:9200 -p 9300:9300 --name es02 镜像id

访问127.0.0.1:9200

集群名为docker-cluster,所以我们要修改application.properties的配置了

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

我们再次进行测试,测试可以通过了 。我们访问http://127.0.0.1:9200/gf/book/1,可以得到我们存入的索引信息。

源码:https://github.com/gf-huanchupk/springbootlearning

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。