1、概述
- Spring Data ElasticSearch 对原生的 ElasticSearch 简化
- 特点:
-
- 基于 @Configuration 配置,只要在 yml 文件中配置,项目中就可以使用。
-
- 工具类 ElasticsearchTemplate ES 模板,类似通用 mapper,通过对象操作 ES
-
- 提供持久层接口 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);
}
}
- Optional类是Java8为了解决null值判断问题
- JDK8特性(自学):https://www.jianshu.com/nb/27231419
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 进行查询
-
- 修改 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); }
-
- 调用自定义方法,完成功能
@Test public void demo03() { List<ESBook> list = esBookRepository.findByTitle("测试二"); System.out.println(list); }
-
-
实例2:区间查询,价格 50-300
-
- 声明
//实例2:区间查询,价格50-300 public List<ESBook> findByPriceBetween(Float start, Float end);
-
- 调用
@Test public void demo04() { List<ESBook> list = esBookRepository.findByPriceBetween(50f, 300f); System.out.println(list); }
-
-
实例3:查询价格 >=290
-
- 声明
//实例3:查询价格>=290 public List<ESBook> findByPriceGreaterThanEqual(Float price);
-
- 调用
@Test public void demo05(){ List<ESBook> list = esBookRepository.findByPriceGreaterThanEqual(290f); System.out.println(list); }
-
-
实例4:区间查询,价格 50-300,且按照 images 进行降序排序
-
- 声明
//实例4:区间查询,价格50-300,且按照image进行降序排序 public List<ESBook> findByPriceBetweenOrderByImagesDesc(Float start, Float end);
-
- 调用
@Test public void demo06(){ List<ESBook> list = esBookRepository.findByPriceBetweenOrderByImagesDesc(50f,300f); System.out.println(list); }
-
来源:oschina
链接:https://my.oschina.net/tingqianyunluo/blog/3234223