整合Spring Data ElasticSearch

与世无争的帅哥 提交于 2020-04-14 12:11:56

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

1、概述

  • Spring Data ElasticSearch 对原生的 ElasticSearch 简化
  • 特点:
      1. 基于 @Configuration 配置,只要在 yml 文件中配置,项目中就可以使用。
      1. 工具类 ElasticsearchTemplate ES 模板,类似通用 mapper,通过对象操作 ES
      1. 提供持久层接口 Repository,相当于通过 mapper

Elasticsearch 和 传统数据库对比

关系型数据库(如 MySQL) 非关系型数据库(Es)
数据库 Database 索引 Index
表 Table 类型 Type
数据行 Row 文档 Document
数据列 Column 字段 field

基本概念

专业术语 概念
Node(节点) 单个的装有Elasticsearch服务并且提供故障转移和扩展的服务器。
Cluster(集群) 一个集群就是由一个或多个node组织在一起,共同工作,共同分享整个数据具有负载均衡功能的集群。
Document(文档) 一个文档是一个可被索引的基础信息单元。
Index(索引) 索引就是一个拥有几分相似特征的文档的集合。
Type(类型) 一个索引中,你可以定义一种或多种类型。
Field(列) Field是Elasticsearch的最小单位,相当于数据的某一列。
Shards(分片) Elasticsearch将索引分成若干份,每个部分就是一个shard。
Replicas(复制) Replicas是索引一份或多份拷贝。

2、搭建环境

  • 随便创建一个子模块,学习Elasticsearch

  • 步骤一:修改 pom.xml 文件,添加对应坐标。添加ES的依赖

    <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>
            <!--自定义common-->
            <dependency>
                <groupId>com.czxy</groupId>
                <artifactId>changgou3_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;

/**
 * @author 庭前云落
 * @Date 2020/4/13 20:38
 * @description
 */
@Configuration
public class ESConfig {
    @PostConstruct
    public void init(){
        System.setProperty("es.set.netty.runtime.available.processors","false");
    }
}

3、索引操作

3.1、映射类

  • 映射类:用于表示 java 的数据和 elasticsearch 的数据对应关系。在spring data elasticsearch 中使用注解完成。

    注解名称 描述
    @Document 用于配置Java类与索引/类型对应关系<br/> - indexName:对应索引库名称<br/> - type:对应在索引库中的类型<br/> - shards:分片数量,默认5<br/> - replicas:副本数量,默认1
    @Id 唯一标识
    @Field 用于配置Java属性和es的字段对应关系<br>– type:字段类型,枚举:FieldType<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 庭前云落
 * @Date 2020/4/13 20:40
 * @description
 */
@Document(indexName = "czxy56",type = "book",shards = 4,replicas = 2)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ESBook {
    @Id
    private Long id;

    @Field(type= FieldType.Text, analyzer = "ik_max_word")
    private String title;//标题

    @Field(type=FieldType.Keyword , index = true)
    private String images;//图片

    @Field(type=FieldType.Float)
    private Float price;//价格
}

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

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

    • 创建索引:createIndex(映射类.class)
    • 添加映射:putMapping(映射类.class)
    • 删除索引:deleteIndex(映射类.class)
  • 一、测试类中,注入 ElasticsearchTemplate

  • 二、调用对应的 API 进行操作

    package com.czxy.elasticsearch;
    
    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 庭前云落
     * @Date 2020/4/13 20:33
     * @description
     */
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = TestApplication.class)
    public class TestES {
    
        @Resource
        private ElasticsearchTemplate elasticsearchTemplate;
    
    
        @Test
        public void demo01() {
            //创建索引,会根据czxy56类的@Document注解信息来创建
            elasticsearchTemplate.createIndex(ESBook.class);
        }
    
        @Test
        public void demo02() {
            //配置映射,会根据czxy56类中的id、Field等字段来自动完成映射
            elasticsearchTemplate.putMapping(ESBook.class);
        }
    
        @Test
        public void demo03() {
            //删除映射,可以根据类名或索引名删除
            elasticsearchTemplate.deleteIndex(ESBook.class);
        }
    }
    
    

4、文档操作(增删改)

4.1、顶级接口:Repository

  • Spring Data Elasticsearch 提供了一个顶级接口 Repository,你不用写任何DAO处理,自动根据方法名或类的信息进行CRUD操作。只要你定义一个接口,然后继承Repository提供的一些子接口,就能具备各种基本的CRUD功能。

    • PagingAndSortingRepository:(第二代) 完成分页和排序功能
    • ElasticsearchCrudRepository:(第三代) 增删改查功能
    • ElasticsearchRepository:(第四代) 完成所有功能
  • 编写:只需要编写子接口,继承 ElasticsearchRepository 即可,且Spring Data 自动加载该类。

  • 注意:接口在使用时,需要确定 2 个泛型信息
    • 第一个泛型:映射类,这里是ESBook
    • 第二个泛型:映射类唯一标识的类型,ID的类型 Long
package com.czxy.Repository;

import com.czxy.vo.ESBook;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.util.List;

/**
 * @author 庭前云落
 * @Date 2020/4/13 20:49
 * @description
 */
public interface ESBookRepository extends ElasticsearchRepository<ESBook, Long> {

}

4.2、添加数据

方法名 描述
save(T t) 保存一个数据
saveAll( Iterable ) 保存一组数据
package com.czxy.elasticsearch;

import com.czxy.Repository.ESBookRepository;
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.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.util.ArrayList;

/**
 * @author 庭前云落
 * @Date 2020/4/13 20:51
 * @description
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class TestData {

    @Resource
    private ESBookRepository esBookRepository;

    @Test
    public void demo01() {
        ESBook esBook = new ESBook(1L, "测试一", "1.jpg", 998f);
        //添加
        esBookRepository.save(esBook);
    }

    @Test
    public void demo02() {
        ArrayList<ESBook> esBooks = new ArrayList<>();
        esBooks.add(new ESBook(2L, "测试二", "2.jpg", 456f));
        esBooks.add(new ESBook(3L, "测试三", "3.jpg", 290f));
        esBooks.add(new ESBook(4L, "测试四", "4.jpg", 100f));
        //添加一组数据  
        esBookRepository.saveAll(esBooks);
    }
}

4.3、修改数据

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

  • 区分标准:

    • 如果 id 的值有对应的数据,则进行更新操作。
    • 如果 id 的值没有对应的数据,则进行添加操作。
        @Test
        public void demo03() {
            //更新数据,es中必须有id=1的数据
            ESBook esBook = new ESBook(1L, "测试一改", "1111.jpg", 1998f);
            esBookRepository.save(esBook);
        }
    

4.3、删除数据

  @Test
    public void demo04() {
        ESBook esBook = new ESBook();
        esBook.setId(1L);
        esBookRepository.delete(esBook);
    }

4.4、查询

方法 描述
findAll() 查询所有
findById( Long ) 通过id查询详情
package com.czxy.elasticsearch;

import com.czxy.Repository.ESBookRepository;
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.test.context.junit4.SpringRunner;

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

/**
 * @author 庭前云落
 * @Date 2020/4/13 21:01
 * @description
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class TestESFind {
    @Resource
    private ESBookRepository esBookRepository;

    @Test
    public void demo01() {
        //查询所有
        Iterable<ESBook> iterable = esBookRepository.findAll();
        Iterator<ESBook> iterator = iterable.iterator();
        while (iterator.hasNext()) {
            ESBook esBook = iterator.next();
            System.out.println(esBook);
        }
    }

    @Test
    public void demo02() {
        //通过id查询详情
        Optional<ESBook> optional = esBookRepository.findById(2L);
        ESBook esBook = optional.get();
        System.out.println(esBook);
    }
}

4.5、自定义方法查询

  • 自定义查询,Spring Data 根据约定的方法名进行自动查询。
    • 约定方法名要求:findBy 字段名|关键字 等
    • 例如:findByTitle(值) 根据 title 进行查询
Keyword Sample Elasticsearch Query String
And findByNameAndPrice {"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
Or findByNameOrPrice {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
Is findByName {"bool" : {"must" : {"field" : {"name" : "?"}}}}
Not findByNameNot {"bool" : {"must_not" : {"field" : {"name" : "?"}}}}
Between findByPriceBetween {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
LessThanEqual findByPriceLessThan {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
GreaterThanEqual findByPriceGreaterThan {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
Before findByPriceBefore {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
After findByPriceAfter {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
Like findByNameLike {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
StartingWith findByNameStartingWith {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
EndingWith findByNameEndingWith {"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}}
Contains/Containing findByNameContaining {"bool" : {"must" : {"field" : {"name" : {"query" : "**?**","analyze_wildcard" : true}}}}}
In findByNameIn(Collection<String>names) {"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}
NotIn findByNameNotIn(Collection<String>names) {"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}}
Near findByStoreNear Not Supported Yet !
True findByAvailableTrue {"bool" : {"must" : {"field" : {"available" : true}}}}
False findByAvailableFalse {"bool" : {"must" : {"field" : {"available" : false}}}}
OrderBy findByAvailableTrueOrderByNameDesc {"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}}
  • 实例1:根据 title 进行查询

      1. 修改 response 自定义接口,添加方法声明
      package com.czxy.Repository;
      
      import com.czxy.vo.ESBook;
      import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
      
      import java.util.List;
      
      /**
       * @author 庭前云落
       * @Date 2020/4/13 20:49
       * @description
       */
      public interface ESBookRepository extends ElasticsearchRepository<ESBook, Long> {
          //实例1:根据title查询
          public List<ESBook> findByTitle(String title);
      }
      
      
      1. 调用自定义方法,完成功能
          @Test
          public void demo03() {
              List<ESBook> list = esBookRepository.findByTitle("测试二");
              System.out.println(list);
          }
      
  • 实例2:区间查询,价格 50-300

      1. 声明
           //实例2:区间查询,价格50-300
          public List<ESBook> findByPriceBetween(Float start, Float end);
      
      1. 调用
          @Test
          public void demo04() {
              List<ESBook> list = esBookRepository.findByPriceBetween(50f, 300f);
              System.out.println(list);
          }
      
  • 实例3:查询价格 >=290

      1. 声明
          //实例3:查询价格>=290
          public List<ESBook> findByPriceGreaterThanEqual(Float price);
      
      
      1. 调用
          @Test
          public void demo05(){
              List<ESBook> list = esBookRepository.findByPriceGreaterThanEqual(290f);
              System.out.println(list);
          }
      
  • 实例4:区间查询,价格 50-300,且按照 images 进行降序排序

      1. 声明
      //实例4:区间查询,价格50-300,且按照image进行降序排序 
      public List<ESBook> findByPriceBetweenOrderByImagesDesc(Float start, Float end);
      
      
      1. 调用
          @Test
          public void demo06(){
              List<ESBook> list = esBookRepository.findByPriceBetweenOrderByImagesDesc(50f,300f);
              System.out.println(list);
          }
      
      
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!