Spring Boot 11. 与检索

ElasticSearch

一、检索

  • 我们的应用经常需要添加检索功能,开源的 ElasticSearch 是目前全文搜索引擎的首选。他可以快速的存储、搜索和分析海量数据。Spring Boot通过整合Spring Data ElasticSearch为我们提供了非常便捷的检索功能支持;
  • Elasticsearch是一个分布式搜索服务,提供Restful API,底层基于Lucene,采用多shard(分片)的方式保证数据安全,并且提供自动resharding的功能,github等大型的站点也是采用了ElasticSearch作为其搜索服务,

二、概念

  • 以 员工文档 的形式存储为例:一个文档代表一个员工数据。存储数据到 ElasticSearch 的行为叫做 索引 ,但在索引一个文档之前,需要确定将文档存储在哪里。
    • 一个 ElasticSearch 集群可以 包含多个 索引 ,相应的每个索引可以包含多个 类型 。 这些不同的类型存储着多个 文档 ,每个文档又有 多个 属性 。
  • 类似关系:
    索引-数据库
    类型-表
    文档-表中的记录
    属性-列
    image

三、整合 ElasticSearch 测试

3.1 docker 下载 ElasticSearch

  • 设置max_map_count不能启动es会启动不起来
    # 查看max_map_count的值 默认是65530
    cat /proc/sys/vm/max_map_count
    # 重新设置max_map_count的值
    sysctl -w vm.max_map_count=262144
    
  • 下载镜像并运行
    docker pull elasticsearch:7.7.0  # 下载 elasticsearch,也可以自定义版本
    docker images # 查看下载的镜像
    # elasticsearch 默认初始的时候会占用两个G的内存,-e 限制内存的使用,否则会报错,
    # -d 后台启动,-p 指定端口映射,默认web通信使用的是 9200端口,分布式的情况下是 9300
    # 启动镜像
    docker run --name elasticsearch -d -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -e "discovery.type=single-node" -p 9200:9200 -p 9300:9300 <IMAGE_ID>
    
  • 浏览器访问 ip:9200
    {
      "name" : "6ab504425d8f",
      "cluster_name" : "docker-cluster",
      "cluster_uuid" : "YYDKqci1TxSLYo--h2Znxg",
      "version" : {
        "number" : "7.7.0",
        "build_flavor" : "default",
        "build_type" : "docker",
        "build_hash" : "81a1e9eda8e6183f5237786246f6dced26a10eaf",
        "build_date" : "2020-05-12T02:01:37.602180Z",
        "build_snapshot" : false,
        "lucene_version" : "8.5.1",
        "minimum_wire_compatibility_version" : "6.8.0",
        "minimum_index_compatibility_version" : "6.0.0-beta1"
      },
      "tagline" : "You Know, for Search"
    }
    

3.2 SpringBoot整合 ES

3.2.1 pom

    <!--父模块-->
    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>1.5.10.RELEASE</version>
    </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>
        <!--引入web模块 spring-boot-starter :springboot场景启动器,帮我们导入了web模块正常运行所依赖的 jar包-->
        <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>
        </dependency>
        <!--导入配置文件处理器,配置文件进行绑定就会有提示-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <!--es的启动器,SpringBoot默认使用 SpringData ElasticSearch模块进行操作-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
    </dependencies>

    <!--这个插件,可用将应用打包成一个可执行的 jar包-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

3.2.2 配置原理

  • 我们可以在 spring-boot-autoconfigure-1.5.10.RELEASE.jar包中查看
  • SpringBoot默认支持两种技术和 ES交互
    1. Jest(org.springframework.boot.autoconfigure.elasticsearch.jest)
      • 默认是不生效了,需要导入 jest的工具包 io.searchbox.client.JestClient)
    2. SpringData ElasticSearch(org.springframework.boot.autoconfigure.data.elasticsearch)

3.3.3 ElasticsearchTemplate 操作 ES

  • 这里因为 springBoot的版本过低 1.5.10而spring-data-elasticsearch版本2.1.10
  • 需要升级 springboot版本,或者安装对应的 es,这里我们按照对应的 es(2.4.6)
# 在你的 ip:9200 可以看到 cluster_name
spring.data.elasticsearch.cluster-name=elasticsearch
spring.data.elasticsearch.cluster-nodes=ip:9300
@Document(indexName = "atguigu", indexStoreType = "book")
public class Book {
    private Integer id;
    private String bookName;
    private String author;
}
public interface BookRepository extends ElasticsearchRepository<Book, Integer> {
}
    @Autowired
    BookRepository bookRepository;

    @Test
    public void testDataES() {
        //浏览器访问 ip:9200/atguigu/boot/1
        // 官方文档
        // https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#repositories.query-methods
        bookRepository.index(new Book(1, "大话西游", "jack"));
    }

3.3.4 使用 JestClient操作ES

        <!--es的启动器,SpringBoot默认使用 SpringData ElasticSearch模块进行操作-->
        <!--<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>-->
        <!--使用 jest操作 es-->
        <!-- https://mvnrepository.com/artifact/io.searchbox/jest -->
        <dependency>
            <groupId>io.searchbox</groupId>
            <artifactId>jest</artifactId>
            <version>6.3.1</version>
        </dependency>
spring.elasticsearch.jest.uris=http://ip:9200
// 要实现 Serializable 接口
public class Article implements Serializable {
    @JestId //标识这是一个 主键
    private Integer id;
    private String author;
    private String title;
    private String content;
    // 省略 set get 其他
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootApplicationESTest {
    @Autowired
    JestClient jestClient;

    @Test
    public void testES() {
        //1. 给es索引保存一个文档
        Article article = new Article(1, "zhangsan", "这是一个好消息", "hellowrod");
        // 构建一个索引功能
        Index index = new Index.Builder(article).index("atguigu").type("news").build();
        try {
            // 执行
            //浏览器访问 http://ip:9200/atguigu/news/1
            //或者 http://ip:9200/_search
            jestClient.execute(index);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testSearch() {
        //{query:{match:{last_name:hello}}}
        //查询表达式
        String json = "{" + "\"query\"" + ":" + "{" + "\"match\"" + ":" + "{" + "\"author\"" + ":" + "\"zhangsan\"" + "}" + "}" + "}";
        //构建搜索功能
        Search build = new Search.Builder(json).addIndex("atguigu").addType("news").build();
        try {
            SearchResult result = jestClient.execute(build);
            System.out.println(result.getJsonString());
            //{"took":3,"timed_out":false,"_shards":{
            // "total":1,"successful":1,"skipped":0,"failed":0},
            // "hits":{"total":{"value":1,"relation":"eq"},"max_score":0.2876821,
            // "hits":[{"_index":"atguigu","_type":"news","_id":"1","_score":0.2876821,
            // "_source":{"id":1,"author":"zhangsan","title":"这是一个好消息","content":"hellowrod"}}]}}
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
posted @ 2022-01-01 19:23  MikiKawai  阅读(35)  评论(0编辑  收藏  举报