学习使用Spring Data Elasticsearch,可以先了解一下Elasticsearch基础使用:基础使用
为什么Elasticsearch给我们提供了Java客户端,我们还要学习Spring Data Elasticsearch?
因为Elasticsearch提供的Java客户端有一些地方不太方便,
- 很多地方需要自己拼接字符串
- 需要自己将对象序列化成json存储
- 查询结果也需要自己反序列化。
所以我们今天去学习一下 Spring Data Elasticsearch。
一、Spring Data Elasticsearch 介绍
Spring Data Elasticsearch是Spring Data项目下的一个子模块。
Spring Data Elasticsearch是Spring Data项目下的一个子模块。
查看 Spring Data的官网:http://projects.spring.io/spring-d
Spring Data的使命是为数据访问提供熟悉且一致的基于Spring的编程模型,同时仍保留底层数据存储的特殊特性。
它使得使用数据访问技术,关系数据库和非关系数据库,map-reduce框架和基于云的数据服务变得容易。这是一个总括项目,其中包含许多特定于给定数据库的子项目。这些令人兴奋的技术项目背后,是由许多公司和开发人员合作开发的。
Spring Data 的使命是给各种数据访问提供统一的编程接口,不管是关系型数据库(如MySQL),还是非关系数据库(如Redis),或者类似Elasticsearch这样的索引数据库。从而简化开发人员的代码,提高开发效率。
包含很多不同数据操作的模块:
Spring Data Elasticsearch的页面:https://projects.spring.io/spring-data-elasticsearch/
特征:
-
支持Spring的基于
@Configuration
的java配置方式,或者XML配置方式 -
提供了用于操作ES的便捷工具类
ElasticsearchTemplate
。包括实现文档到POJO之间的自动智能映射。 -
利用Spring的数据转换服务实现的功能丰富的对象映射
-
基于注解的元数据映射方式,而且可扩展以支持更多不同的数据格式
-
根据持久层接口自动生成对应实现方法,无需人工编写基本操作代码(类似mybatis,根据接口自动得到实现)。当然,也支持人工定制查询
二、快速入门
创建一个maven工程,然后添加依赖,修改配置,创建启动类:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.yuanxion.elasticsearch</groupId>
<artifactId>yuanxion-elasticsearch</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>elasticsearch</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml
spring:
data:
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: 虚拟机或云服务器地址:9300
ElasticsearchApplication
@SpringBootApplication
public class ElasticsearchApplication {
public static void main(String[] args) {
SpringApplication.run(ElasticsearchApplication.class);
}
}
添加实体类:
public class Item {
Long id;
String title; //标题
String category;// 分类
String brand; // 品牌
Double price; // 价格
String images; // 图片地址
//记得生成getter、setter方法
}
映射
Spring Data通过注解来声明字段的映射属性,有下面的三个注解:
-
@Document
作用在类,标记实体类为文档对象,一般有四个属性-
indexName:对应索引库名称
-
type:对应在索引库中的类型
-
shards:分片数量,默认5
-
replicas:副本数量,默认1
-
-
@Id
作用在成员变量,标记一个字段作为id主键 -
@Field
作用在成员变量,标记为文档的字段,并指定字段映射属性:-
type:字段类型,取值是枚举:FieldType
-
index:是否索引,布尔类型,默认是true
-
store:是否存储,布尔类型,默认是false
-
analyzer:分词器名称:ik_max_word
-
在刚刚添加的实体类上添加注解来映射属性:
去测试里试一下。
1.创建索引和映射
启动测试后,去查询一下:
索引和映射都创建成功了。
2. 删除索引
@Test
public void deleteIndex() {
elasticsearchTemplate.deleteIndex("item");
}
Spring Data 的强大之处,在于我们不用写任何DAO处理,自动根据方法名或类的信息进行CRUD操作。我们只要定义一个接口,然后继承Repository提供的一些子接口,就能具备各种基本的CRUD功能。
我们来定义接口,然后继承它:
下面就可以来使用了。
3.新增文档
先给实体类添加构造方法,无参的和全参的。
测试新增文档:
查询看看:
4.查询
@Test
public void testQuery(){
//查询所有
Optional<Item> optional = this.itemRepository.findById(1l);
System.out.println(optional.get());
}
@Test
public void testFind(){
// 查询全部,并按照价格降序排序
Iterable<Item> items = this.itemRepository.findAll(Sort.by(Sort.Direction.DESC, "price"));
items.forEach(item-> System.out.println(item));
}
自定义方法:
Spring Data 的一个强大功能,是根据方法名称自动实现功能。
比如:你的方法名叫做: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}}}} |
例如:
我们在接口中写了一个根据标题查询的方法,但是不用我们去实现这个方法,Spring Data会帮我们去自动实现!
测试一下:
基本查询:
QueryBuilders给我们提供了大量的静态方法,用于生成各种不同类型的查询对象,
例如:词条、模糊、通配符等QueryBuilder对象。
虽然elasticsearch提供了很多可用的查询方式,但是不够灵活。比如如果想用过滤或者聚合查询等就很难了。
所以我们要学习使用自定义查询。
自定义基本查询:
NativeSearchQueryBuilder 是Spring提供的一个查询条件构建器,帮助构建json格式的请求体
Page<item>
:默认是分页查询,因此返回的是一个分页的结果对象,包含属性:
-
totalElements:总条数
-
totalPages:总页数
-
Iterator:迭代器,本身实现了Iterator接口,因此可直接迭代得到当前页的数据。
自定义分页查询:
注意:Elasticsearch中的分页是从第0页开始。
自定义排序查询:
聚合
聚合嵌套