【SpringBoot2.0系列11】SpringBoot之@E

作者: 余空啊 | 来源:发表于2018-09-04 17:30 被阅读15次

    【SpringBoot系列01】初识SpringBoot

    【SpringBoot系列02】SpringBoot之使用Thymeleaf视图模板

    【SpringBoot系列03】SpringBoot之使用freemark视图模板

    【SpringBoot系列04】SpringBoot之使用JPA完成简单的rest api

    【SpringBoot系列05】SpringBoot之整合Mybatis

    【SpringBoot2.0系列06】SpringBoot之多数据源动态切换数据源

    【SpringBoot2.0系列07】SpringBoot之redis使用(Lettuce版本)

    【SpringBoot2.0系列08】SpringBoot之redis数据缓存管理

    【SpringBoot2.0系列09】SpringBoot之rabbitmq使用

    【SpringBoot2.0系列10】SpringBoot之@Scheduled任务调度

    【SpringBoot2.0系列11】SpringBoot之@Elasticsearch完成CURD

    ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    如果在springboot使用Easticsearch呢。在这里我们使用spring-boot-starter-data-elasticsearch。
    它提供一系列简单的api给我们使用,让我们有种操作关系数据库的感觉。
    好了话不多说,先说一下环境。

    • spring boot2.x
    • jdk8
    • elasticsearch5.x(6.x也可以)

    依赖

    引入依赖

      <dependencies>
    
            <!-- lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.16.22</version>
            </dependency>
            <!-- elasticsearch -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    

    在这里我们分别引入elasticsearch跟lombok的依赖,关于lombok的介绍大家可以看看这篇文章 讲的很详细。我这简单的介绍一下在项目中使用Lombok可以减少很多重复代码的书写。比如说getter/setter/toString等方法的编写。

    配置es地址

    在下文中我将用es代替elasticsearch。我们打开application.yml文件 配置如下

      spring:
      data:
        elasticsearch:
          # 集群的名字
          cluster-name: wali
          # 节点的ip与端口 注意端口是9300不是9200
          cluster-nodes: 127.0.0.1:9300
    

    构建文档对象

    假设这是一个商品索引goods,他有一个类型是电脑computer。
    分别有四个字段

    • id 唯一标识
    • name 商品名称
    • number 商品数量
    • desc 商品具体描述
      我们根据上面的描述,编写出对应的实体类
    @Data
    @ToString
    @Accessors(chain = true)
    @Document(indexName = "goods", type = "computer")
    public class Good {
    
        /**
         * 主键,注意这个搜索是id类型是string,与我们常用的不同
         * Id注解加上后,在Elasticsearch里相应于该列就是主键了,在查询时就可以直接用主键查询
         */
        @Id
        private String id;
    
        private String name;
    
        private String desc;
    
        private Integer number;
    
    }
    

    其中@Data @ToString @Accessors(chain = true) 是属于lombok注解。

    • @Data 会自动上传get/set方法
    • @ToString 会生成tostring方法
    • @Accessors(chain = true) 会让我们set方法可以链式调用
      @Document注解

    @Document注解里面的几个属性,类比mysql的话是这样:
    indexName –> 索引库的名称,建议以项目的名称命名,就相当于数据库DB
    type –> 类型,建议以实体的名称命名Table ,就相当于数据库中的表table
    Document –> row 就相当于某一个具体对象

    jpa构建文档库

    接着,我们可以通过jpa构建文档库,来操作我们的goods对应的文档。
    因为我们引入的是spring data的elasticsearch所以它遵循spring data的接口,也就是说操作elasticSearch与操作spring data jpa的方法是完全一样的,我们只将文档库继承ElasticsearchRepository即可。

    public interface GoodRepository extends ElasticsearchRepository<Good, String> {
    
       /**
         * 根据商品名称查询 分页
         * @param name
         * @param pageable
         * @return
         */
        Page<Good> findByName(String name, Pageable pageable);
    
    }
    

    然后创建对应的测试类。前面说过快捷键ctrl+shift+t
    并且编写测试方法,我们分别需要测试添加 删除 修改 查询 分页查询方法。

    @Component
    @FixMethodOrder(MethodSorters.NAME_ASCENDING)
    public class GoodRepositoryTest extends Chapter10ApplicationTests {
    
        @Autowired
        private GoodRepository goodRepository;
        
        @Test
        public void save(){}
    
        @Test
        public void update(){}
    
        @Test
        public void select(){}
    
        @Test
        public void delete(){}
    
        @Test
        public void findByName() {
           
        }
    }
    

    上面代码我们是通过基础主测试类然后使用@Component注解就可以,这样就不需要每个测试都要@SpringTest注解与@RunWith注解了
    另外@FixMethodOrder(MethodSorters.NAME_ASCENDING)这个注解是表示按照方法名的顺序来排序,不然它不会按照我们方法书写的顺序执行,那么就有可能导致,还没save就select,这样就会失败了。
    接下来继续编写方法体。goodRepository跟我们直接data-jparespository用法基本一致。都有继承save,delete,find方法的。

    @Test
        public void save(){
            Good good = new Good();
            good.setId("100")
                    .setName("联想e541")
                    .setDesc("联想e系列")
                    .setNumber(10);
            Good result = goodRepository.save(good);
            Assert.assertNotNull(result);
        }
    
        @Test
        public void select(){
            // 需要注意find方法返回的死Optional对象 需要调用get方法返回具体的实体类对象
            Good result = goodRepository.findById("100").get();
            Assert.assertNotNull(result);
    
        }
    
        @Test
        public void update(){
            Good result = goodRepository.findById("100").get();
            result.setNumber(300);
            // 更新也是调用save方法
            Good good = goodRepository.save(result);
            Assert.assertNotNull(good);
    
        }
    
    
    
        @Test
        public void delete(){
            goodRepository.deleteById("100");
        }
    

    我们首先测试增删改查方法。并且通过Assert断言来判断。

    image.png

    测试通过,
    接下来我测试一下分页查询方法,首页我们看一下es中、goods索引computer类别下有哪些文档。

    curl -XGET  'http://127.0.0.1:9200/goods/computer/_search?pretty'
    

    结果如下

    {
      "took" : 21,
      "timed_out" : false,
      "_shards" : {
        "total" : 5,
        "successful" : 5,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : 3,
        "max_score" : 1.0,
        "hits" : [
          {
            "_index" : "goods",
            "_type" : "computer",
            "_id" : "_search",
            "_score" : 1.0,
            "_source" : {
              "id" : "_search",
              "name" : "macbook",
              "number" : 20,
              "desc" : "macbook air"
            }
          },
          {
            "_index" : "goods",
            "_type" : "computer",
            "_id" : "2",
            "_score" : 1.0,
            "_source" : {
              "id" : "2",
              "name" : "think pad",
              "number" : 20,
              "desc" : "联想旗下thinkpad系列"
            }
          },
          {
            "_index" : "goods",
            "_type" : "computer",
            "_id" : "1",
            "_score" : 1.0,
            "_source" : {
              "id" : "1",
              "name" : "macbook",
              "number" : 20,
              "desc" : "macbook pro"
            }
          }
        ]
      }
    }
    

    我看到在computer类别中存有三条文档,name分别是 macbook think pad macbook,所以我们查询一下name=macbook的文档,pageSize=1,pageNum=1.

    @Test
        public void findByName() {
            String name = "macbook";
            Pageable pageable = new PageRequest(1,1);
            Page<Good> goods = goodRepository.findByName(name, pageable);
            System.out.println(goods.getContent());
            Assert.assertEquals(1, goods.getSize());
    
        }
    

    我们查询name为macbook的数据,并且限制每页一条,所以我们查询的结果总数应该是一条。结果如下。


    在这节,我们了解了springboot与es的curd操作,都是比较简单的,那么下节我们会详细了解springboot对es如何进行复杂查询,与聚合查询。
    最后本节的配套代码地址为https://github.com/YuKongEr/SpringBoot-Study/tree/master/chapter10

    最后欢迎大家关注一下我的个人公众号。一起交流一起学习,有问必答。


    公众号

    相关文章

      网友评论

        本文标题:【SpringBoot2.0系列11】SpringBoot之@E

        本文链接:https://www.haomeiwen.com/subject/uragwftx.html