Spring Boot 11. 与检索


ElasticSearch

一、检索

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

二、概念

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

三、整合 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 
    
  • 浏览器访问 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

    
    
        spring-boot-starter-parent
        org.springframework.boot
        1.5.10.RELEASE
    
    
        utf-8
        utf-8
        1.8
    
    
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.springframework.boot
            spring-boot-starter-test
        
        
        
            org.springframework.boot
            spring-boot-configuration-processor
            true
        
        
        
            org.springframework.boot
            spring-boot-starter-data-elasticsearch
        
    

    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

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)
      • Client 节点信息 clusterNodes ;clusterName
      • ElasticsearchTemplate 操作 es
      • 编写一个 ElasticsearchRepository 的子接口来操作ES
      • es版本有可能不合适,如果版本不合适:1. 升级 springboot版本,2. 安装对应的 es
      • https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#preface.versions

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 {
}
    @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

        
        
        
        
        
            io.searchbox
            jest
            6.3.1
        
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();
        }
    }
}

相关