02. ElasticSearch (Spring Data ElasticSearch)

大憨熊 提交于 2020-04-14 23:44:08

【推荐阅读】微服务还能火多久?>>>

1. 概述

  • Spring Data Elasticsearch 对原生的 Elasticsearch 简化

  • 特点:

    • 基于Configuration配置,只要在yml文件中配置,项目就可以使用
    • 工具类 ElasticsearchTemplate ES模板,类似女通用mapper,通过对象操作ES
    • 提供持久层接口 Repository,无需编写基本操作代码(蕾西与mybatis,根据接口自动得到实现),也支持自定义查询

2. 环境搭建

  • 步骤一: 修改pom.xml文件,导入坐标

  • 步骤二: 修改yml文件,添加Elasticsearch配置信息

  • 步骤三: 创建一个配置类,项目启动时时,设置一个参数,防止运行时异常

  • 步骤四: 编写测试方法

  • 步骤一: 修改pom.xml文件,导入坐标

    <dependencies>
            <!--redis-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
            </dependency>
            <!--测试-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
            </dependency>
            <dependency>
                <groupId>com.czxy</groupId>
                <artifactId>changgou_common</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
                <!--es-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            </dependency>
    
        </dependencies>
    
  • 步骤二: 修改yml文件,添加Elasticsearch配置信息

    spring:
      redis:
        database:   1     #确定使用库
        host: 127.0.0.1   #redis服务地址
        port: 6379      #redis 端口号
      data:
        elasticsearch:
          cluster-name: elasticsearch
          cluster-nodes: 127.0.0.1:9300
    
  • 步骤三: 创建一个配置类,项目启动时时,设置一个参数,防止运行时异常

    package com.czxy.config;
    
    import org.springframework.context.annotation.Configuration;
    
    import javax.annotation.PostConstruct;
    
    /**
     * Created by Pole丶逐.
     */
    @Configuration
    public class ESConfig {
        /**
         * 项目启动时,设置一个参数
         */
        @PostConstruct
        public void init() {
            System.setProperty("es.set.netty.runtime.available.processors", "false");
        }
    }
    
    
  • 步骤四: 编写测试方法

    package com.czxy.test;
    
    import com.czxy.TestApplication;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    /**
     * [@Author](https://my.oschina.net/arthor) Pole丶逐
     * [@Date](https://my.oschina.net/u/2504391) 2020/4/13 20:39
     * [@E-mail](https://my.oschina.net/rosolio)
     */
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = TestApplication.class)
    public class Demo01 {
    
        @Test
        public void test(){
            System.out.println("AAA");
        }
    }
    
    

3. 索引操作

3.1 创建映射类

  • 映射类: 用于表示java数据和Elasticsearch中数据对应关系.在Spring Data Elasticsearch使用注解完成

    名称 修饰位置 参数
    @Document 表示java数据和Elasticsearch中数据对应关系 indexName: 对应索引名称<br/>type: 对应索引库中的类型 <br/>shards: 分片数量 <br/>replicas: 副本数量
    @Id 唯一标识
    @Field java属性和es字段的对应关系 type: 字段类型<br/>analyzer: 分词器名称<br/>index: 是否索引,默认为true<br/>store: 是否存储,默认为false
  • 实现类:

    package com.czxy.vo;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import org.springframework.data.annotation.Id;
    import org.springframework.data.elasticsearch.annotations.Document;
    import org.springframework.data.elasticsearch.annotations.Field;
    import org.springframework.data.elasticsearch.annotations.FieldType;
    
    /**
     * @Author Pole丶逐
     * @Date 2020/4/13 20:55
     * @E-mail
     */
    @NoArgsConstructor
    @AllArgsConstructor
    @Data
    @Document(indexName = "czxy56",type = "book",shards = 4,replicas = 2)
    public class ESBook {
    
        @Id
        private Long id;
    
        @Field(type = FieldType.Text,analyzer = "ik_max_word")
        private String title;
    
        @Field(type = FieldType.Keyword)
        private String images;
    
        @Field(type = FieldType.Float)
        private Double price;
    }
    
    

3.2 创建索引,添加映射,删除索引

  • ElasticsearchTemplate工具类提供对应方法完成以下功能

  • 步骤一: 直接注入ElasticsearchTemplate,spring容器中自动创建

  • 步骤二: 调用对应API操作

    package com.czxy.test;
    
    import com.czxy.TestApplication;
    import com.czxy.vo.ESBook;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import javax.annotation.Resource;
    
    /**
     * @Author Pole丶逐
     * @Date 2020/4/13 21:00
     * @E-mail
     */
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = TestApplication.class)
    public class TestES {
    
        @Resource
        private ElasticsearchTemplate elasticsearchTemplate;
    
        @Test
        public void test1(){
            // 创建索引
            elasticsearchTemplate.createIndex(ESBook.class);
        }
    
        @Test
        public void test2(){
            //创建映射
            elasticsearchTemplate.putMapping(ESBook.class);
        }
    
        @Test
        public void test3(){
            //删除索引
            elasticsearchTemplate.deleteIndex(ESBook.class);
        }
    
    
    }
    
    

4. 文档操作(增删改)

  • 实现接口: ElasticsearchRepository,实现了所有功能

  • 只需要继承 **ElasticsearchRepository **接口即可,Spring Data 自动加载

    • 参数类型: 泛型

    • 第一个: 映射类(ESBook)

    • 第二个: 映射类唯一标识的类型(Id)

      package com.czxy.repository;
      
      import com.czxy.vo.ESBook;
      import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
      
      import java.util.List;
      
      /**
       * @Author Pole丶逐
       * @Date 2020/4/13 21:15
       * @E-mail
       */
      public interface ESBookRepository extends ElasticsearchRepository<ESBook,Long> {
      
      
      }
      
      

4.1 添加数据

方法名 描述
save() 添加一个数据
saveAll() 添加一组数据
package com.czxy.test;

import com.czxy.TestApplication;
import com.czxy.repository.ESBookRepository;
import com.czxy.vo.ESBook;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;

/**
 * @Author Pole丶逐
 * @Date 2020/4/13 21:14
 * @E-mail
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class TestESData {

    @Resource
    private ESBookRepository esBookRepository;

    @Test
    public void test1(){
        //添加一个数据
        esBookRepository.save(new ESBook(1L,"时间简史","01.jpg",35.0));
    }

    @Test
    public void test2(){
        ArrayList<ESBook> eslist = new ArrayList<>();
        eslist.add(new ESBook(1L,"时间简史","01.jpg",35.0));
        eslist.add(new ESBook(2L,"三体","02.jpg",40.0));
        eslist.add(new ESBook(3L, "人类简史","03.jpg",35.5));
        //添加一个集合
		esBookRepository.saveAll(eslist);
    }

   
}

4.2 修改数据

  • 修改和添加使用的是一个方法

    • 如果id存在则为修改
    • 如果id不存在则为添加
    @Test
    public void test1(){
        //修改数据,id必须存在,否则为添加
        esBookRepository.save(new ESBook(1L,"空间简史","01.jpg",35.0));
    }
    

4.2 删除数据

@Test
public void test3(){
    //  根据对象删除
    //esBookRepository.delete();
    // 根据id删除
    //esBookRepository.deleteById(1L);
    //  删除所有
    //esBookRepository.deleteAll();
}

5. 查询

5.1 基本查询

方法 描述
findAll() 查询所有
findById() 根据id查询
@Test
public void test4(){
    //查询所有
    Iterable<ESBook> iterable = esBookRepository.findAll();
    Iterator<ESBook> iterator = iterable.iterator();
    while (iterator.hasNext()){
        ESBook esBook = iterator.next();
        System.out.println(esBook);
    }
}

@Test
public void test5(){
    //根据id查询
    Optional<ESBook> optional = esBookRepository.findById(1L);
    ESBook esBook = optional.get();
    System.out.println(esBook);
}

5.2 自定义方法

  • Spring Data 根据约定的方法名进行自动查询

    • 要求: findBy字段 | 关键字
  • 实例:

    package com.czxy.repository;
    
    import com.czxy.vo.ESBook;
    import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
    
    import java.util.List;
    
    /**
     * @Author Pole丶逐
     * @Date 2020/4/13 21:15
     * @E-mail
     */
    public interface ESBookRepository extends ElasticsearchRepository<ESBook,Long> {
    
        //根据title查询
        List<ESBook> findByTitle(String title);
    	//根据price查询区间
        List<ESBook> findByPriceBetween(Double start, Double end);
    	//查询大于等于price
        List<ESBook> findByPriceGreaterThanEqual(Double price);
    }
    
    

5.3 自定义查询

5.3.1 关键字查询: match
  • 查询条件构造器: NativeSearchQueryBuilder

  • 查询: queryBuilder.withQuery( ... )

  • match条件: QueryBuilders.matchQuery("字段","值")

  • 查询: esBookRepository.search( 条件 )

  • 返回值: Page,容器,可以直接遍历获取数据

    package com.czxy.test;
    
    import com.czxy.TestApplication;
    import com.czxy.repository.ESBookRepository;
    import com.czxy.vo.ESBook;
    import org.elasticsearch.index.query.BoolQueryBuilder;
    import org.elasticsearch.index.query.QueryBuilders;
    import org.elasticsearch.search.sort.SortBuilders;
    import org.elasticsearch.search.sort.SortOrder;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import javax.annotation.Resource;
    
    /**
     * @Author Pole丶逐
     * @Date 2020/4/14 15:55
     * @E-mail
     */
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = TestApplication.class)
    public class TestData {
    
        @Resource
        private ESBookRepository esBookRepository;
    
        @Test
        public void test1(){
            //创建条件构造器器
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
            //把条件查询match放到查询条件中
            queryBuilder.withQuery(QueryBuilders.matchQuery("title","简史"));
            //创建构造对象并查询
            Page<ESBook> page = esBookRepository.search(queryBuilder.build());
    
            System.out.println("总条数: " + page.getTotalElements());
            System.out.println("总页数: " + page.getTotalPages());
    
            for (ESBook esBook : page) {
                System.out.println(esBook);
            }
        }
    
    }
    
5.3.2 多条件查询: bool -- must/mustNot(交集)
  • 多条件拼凑: BoolQueryBuilder对象

    • QueryBuilders.boolQuery()
  • 并集操作: must()/mustNot()

    @Test
    public void test2(){
        //  创建条件查询构建器
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        //  获得bool查询条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //  拼接查询条件
        boolQueryBuilder.must(QueryBuilders.matchQuery("title","简史"));
        boolQueryBuilder.mustNot(QueryBuilders.matchQuery("title","时间"));
        //  把条件放入查询条件中
        queryBuilder.withQuery(boolQueryBuilder);
        //  构建对象并查询
        Page<ESBook> page = esBookRepository.search(queryBuilder.build());
        //  循环遍历
        page.forEach( esBook -> {
            System.out.println(esBook);
        });
    
    }
    
5.3.3 多条件查询: bool -- should (并集)
  • 交集操作: boolQueryBuilder.should()

    @Test
    public void test3(){
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    
        boolQueryBuilder.should(QueryBuilders.matchQuery("title","人类"));
        boolQueryBuilder.should(QueryBuilders.matchQuery("title","简史"));
    
        queryBuilder.withQuery(boolQueryBuilder);
    
        Page<ESBook> page = esBookRepository.search(queryBuilder.build());
    
        page.forEach( esBook -> {
            System.out.println(esBook);
        });
    }
    
5.3.4 精准查询: term
  • 精准查询: QueryBuilders.termQuery( 字段,值 )

    @Test
    public void test4(){
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    
        queryBuilder.withQuery(QueryBuilders.termQuery("title","简史"));
    
        Page<ESBook> page = esBookRepository.search(queryBuilder.build());
    
        page.forEach(esBook -> {
            System.out.println(esBook);
        });
    
    }
    
5.3.5 区间查询: range
  • 区间查询: QueryBuilders.rangeQuery( 字段 )

    • lt(): 小于
    • lte(): 小于等于
    • gt(): 大于
    • gte(): 大于等于
    @Test
    public void test5(){
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    
        queryBuilder.withQuery(QueryBuilders.rangeQuery("price").gte(35.5).lte(40.0));
    
        Page<ESBook> page = esBookRepository.search(queryBuilder.build());
    
        page.forEach(esBook -> {
            System.out.println(esBook);
        });
    
    }
    
5.3.6 分页查询:
  • 分页查询: queryBuilder.withPageable()

    • 分页工具类: PageRequest.of(pageNum,pageSIze)
    @Test
    public void test6(){
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    
        queryBuilder.withPageable(PageRequest.of(1,2));
    
        Page<ESBook> page = esBookRepository.search(queryBuilder.build());
    
        page.forEach(esBook -> {
            System.out.println(esBook);
        });
    
    }
    
5.3.7 排序查询:
  • 排序查询: queryBuilder.withSort()

    • 排序工具类: SortBuilders.fieldSort(排序字段)
    • 排序方式: order(SortOrder.DESC | SortOrder.ASC)
    @Test
    public void test7(){
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    
        queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));
    
        Page<ESBook> page = esBookRepository.search(queryBuilder.build());
    
        page.forEach(esBook -> {
            System.out.println(esBook);
        });
    
    }
    

6. 总结

  • 查询条件构造器: NativeSearchQueryBuilder
    • 查询条件: queryBuilder.withQuery()
    • 分页条件: queryBuilder.withPageable()
    • 排序条件: queryBuilder.withSort()
    • 构造: build()
  • 查询条件,通过工具类QueryBuilders 获得
    • 关键字查询: matchQuery(字段,值)
    • 多条件查询: boolQuery()
      • 必须有: must()
      • 必须没有; mustNot()
      • 并集: should()
    • 精准查询: termQuery(字段,值)
    • 区间查询: rangeQuery(字段)
      • 大于: gt()
      • 大于等于: gte()
      • 小于: lt()
      • 小于等于: lte()
  • 分页条件: 工具类PageRequest
    • 设置分页参数: PageRequest.of(pageNum,pageSize)
  • 排序字段,通过工具类SortBuilders
    • 排序字段: SortBuilders.fieldSort("字段")
    • 排序方式: order(SortOrder.DESC | SortOrder.ASC)
  • 查询结果: Page对象
    • 总条数: getTotalElements()
    • 总页数: getTotalPages()
    • 第几页: getNumber()
    • 每页个数: getSize()
    • 过得内容: getContent()
    • Page 对象可以直接遍历
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!