学习使用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页开始。
自定义排序查询:
聚合
聚合嵌套

京公网安备 11010502036488号