Java之Spring Data Elasticsearch一篇文章从入门到实战

article/2025/10/5 2:01:32

Elasticsearch提供的Java客户端有一些不太方便的地方:

  • 很多地方需要拼接Json字符串,在java中拼接字符串有多恐怖你应该懂的
  • 需要自己把对象序列化为json存储
  • 查询到结果也需要自己反序列化为对象

因此,我们这里就不讲解原生的Elasticsearch客户端API了。

而是学习Spring提供的套件:Spring Data Elasticsearch。

一、简介

Spring Data Elasticsearch是Spring Data项目下的一个子模块。

查看 Spring Data的官网:http://projects.spring.io/spring-data/
在这里插入图片描述
Spring Data 的使命是为数据访问提供熟悉且一致的基于 Spring 的编程模型,同时仍保留底层数据存储的特​​殊特征。

它使使用数据访问技术、关系和非关系数据库、map-reduce 框架和基于云的数据服务变得容易。

这是一个伞形项目,其中包含许多特定于给定数据库的子项目。

这些项目是通过与这些令人兴奋的技术背后的许多公司和开发商合作开发的。

特征

  • 强大的存储库和自定义对象映射抽象

  • 从存储库方法名称派生的动态查询

  • 提供基本属性的实现域基类

  • 支持透明审计(创建、最后更改)

  • 可以集成自定义存储库代码

  • 通过 JavaConfig 和自定义 XML 命名空间轻松集成 Spring

  • 与 Spring MVC 控制器的高级集成

  • 跨店持久化实验支持

1、Spring Data Elasticsearch

在这里插入图片描述
在这里插入图片描述
Spring Data for Elasticsearch 是 Spring Data 项目的一部分,该项目旨在为新数据存储提供熟悉且一致的基于 Spring 的编程模型,同时保留特定于存储的特性和功能。

Spring Data Elasticsearch 项目提供了与 Elasticsearch 搜索引擎的集成。Spring Data Elasticsearch 的关键功能领域是以 POJO 为中心的模型,用于与 Elastichsearch 文档交互并轻松编写 Repository 样式的数据访问层。

(1)特征

  • Spring 配置支持使用基于 Java 的@Configuration类或用于 ES 客户端实例的 XML 命名空间。

  • ElasticsearchTemplate帮助程序类,可提高执行常见 ES 操作的生产力。包括文档和 POJO 之间的集成对象映射。

  • 功能丰富的对象映射与 Spring 的转换服务集成

  • 基于注释的映射元数据但可扩展以支持其他元数据格式

  • Repository接口的自动实现,包括对自定义查找器方法的支持。

  • 对存储库的 CDI 支持

二、Demo工程的搭建(创建索引)

我们新建一个demo,学习Elasticsearch

在这之前你需要在Linux上安装Elasticsearch:
如果有则不需要安装,入门没有请看我的这篇文章:
https://blog.csdn.net/qq_44757034/article/details/119717907

1、创建一个新的工程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、引入依赖

(1)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>com.itzheng.demo</groupId><artifactId>es-demo</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.2.5.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>

(2)application.yml

在这里插入图片描述
在这里插入图片描述
其中192.168.56.10为你虚拟机或者服务器的ip地址

spring:data:elasticsearch:cluster-name: elasticsearchcluster-nodes: 192.168.56.101:9300

3、设置启动类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.itzheng;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class EsApplication {public static void main(String[] args) {SpringApplication.run(EsApplication.class);}
}

4、创建实体类

在这里插入图片描述
在这里插入图片描述

package com.itzheng.es.pojo;public class Item {private Long id;private String title;   //标题private String category;//分类private String brand;//品牌private Double price;//价格private String images;//图片地址}

添加依赖
在这里插入图片描述

		<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>

完善实体类
在这里插入图片描述

package com.itzheng.es.pojo;import lombok.Data;@Data
public class Item {private Long id;private String title;   //标题private String category;//分类private String brand;//品牌private Double price;//价格private String images;//图片地址
}

5、创建测试类

(1)创建索引库

在这里插入图片描述
在这里插入图片描述

package com.itzheng.es.demo;import com.itzheng.es.pojo.Item;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.junit4.SpringRunner;
/*
Springboot的@RunWith(SpringRunner.class)
注解的意义在于Test测试类要使用注入的类,比如@Autowired注入的类,
有了@RunWith(SpringRunner.class)这些类才能实例化到spring容器中,自动注入才能生效,
不然直接一个NullPointerExecption*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class EsTest {@AutowiredElasticsearchTemplate template;@Testpublic void testCreate(){template.createIndex(Item.class);//创建索引}
}

完善实体类Item,设置在提交到Elasticsearch的时候的索引名称,类型,以及分片
在这里插入图片描述

package com.itzheng.es.pojo;import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Document;@Data
@Document(indexName = "itzhengitem",type = "item",shards = 1)
public class Item {private Long id;private String title;   //标题private String category;//分类private String brand;//品牌private Double price;//价格private String images;//图片地址
}

(2)指定映射关系

1)添加字段映射(继续完善Item实体类)设置类型和主键

映射

Spring Data通过注解来声明字段的映射属性,有下面的三个注解:

  • @Document 作用在类,标记实体类为文档对象,一般有四个属性
    • indexName:对应索引库名称
    • type:对应在索引库中的类型
    • shards:分片数量,默认5
    • replicas:副本数量,默认1
  • @Id 作用在成员变量,标记一个字段作为id主键
  • @Field 作用在成员变量,标记为文档的字段,并指定字段映射属性:
    • type:字段类型,取值是枚举:FieldType
    • index:是否索引,布尔类型,默认是true
    • store:是否存储,布尔类型,默认是false
    • analyzer:分词器名称

示例:
在这里插入图片描述

package com.itzheng.es.pojo;
import lombok.Data;
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;
@Data
@Document(indexName = "itzhengitem",type = "item",shards = 1)
@AllArgsConstructor
@NoArgsConstructor
public class Item {@Field(type = FieldType.Long)@Idprivate Long id;@Field(type = FieldType.Text , analyzer = "ik_smart")//设置类型是文本,并指定分词方式为ik_smartprivate String title;   //标题@Field(type = FieldType.Keyword)  //Keyword设置当前也是文本类型,但是不设置分词private String category;//分类@Field(type = FieldType.Keyword)private String brand;//品牌@Field(type = FieldType.Double)private Double price;//价格@Field(type = FieldType.Keyword,index = false)//index = false设置当前字段不需要被索引,index = 默认是trueprivate String images;//图片地址
}
2)完善测试类,使用映射规则

在这里插入图片描述

package com.itzheng.es.demo;import com.itzheng.es.pojo.Item;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.junit4.SpringRunner;
/*
Springboot的@RunWith(SpringRunner.class)
注解的意义在于Test测试类要使用注入的类,比如@Autowired注入的类,
有了@RunWith(SpringRunner.class)这些类才能实例化到spring容器中,自动注入才能生效,
不然直接一个NullPointerExecption*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class EsTest {@AutowiredElasticsearchTemplate template;@Testpublic void testCreate(){//创建索引库template.createIndex(Item.class);//创建索引//指定映射关系template.putMapping(Item.class);}
}

6、运行测试类

(1)运行测试

在这里插入图片描述
在这里插入图片描述
运行成功
在这里插入图片描述

(2)通过Kabina查看

在这里插入图片描述

GET itzhengitem

返回结果

{"itzhengitem" : {"aliases" : { },"mappings" : {"properties" : {"brand" : {"type" : "keyword"},"category" : {"type" : "keyword"},"id" : {"type" : "keyword"},"images" : {"type" : "keyword","index" : false},"price" : {"type" : "double"},"title" : {"type" : "text","analyzer" : "ik_smart"}}},"settings" : {"index" : {"routing" : {"allocation" : {"include" : {"_tier_preference" : "data_content"}}},"refresh_interval" : "1s","number_of_shards" : "1","provided_name" : "itzhengitem","creation_date" : "1629355397115","store" : {"type" : "fs"},"number_of_replicas" : "1","uuid" : "2cUsvBtgQ4uOARwTuQoHAA","version" : {"created" : "7140099"}}}}
}

在这里插入图片描述

只查看映射

GET itzhengitem/_mapping
{"itzhengitem" : {"mappings" : {"properties" : {"brand" : {"type" : "keyword"},"category" : {"type" : "keyword"},"id" : {"type" : "keyword"},"images" : {"type" : "keyword","index" : false},"price" : {"type" : "double"},"title" : {"type" : "text","analyzer" : "ik_smart"}}}}
}

在这里插入图片描述

三、删除索引

1、编写测试方法

在这里插入图片描述

package com.itzheng.es.demo;import com.itzheng.es.pojo.Item;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.junit4.SpringRunner;
/*
Springboot的@RunWith(SpringRunner.class)
注解的意义在于Test测试类要使用注入的类,比如@Autowired注入的类,
有了@RunWith(SpringRunner.class)这些类才能实例化到spring容器中,自动注入才能生效,
不然直接一个NullPointerExecption*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class EsTest {@AutowiredElasticsearchTemplate template;@Testpublic void testCreate(){//创建索引库template.createIndex(Item.class);//创建索引//指定映射关系template.putMapping(Item.class);}@Testpublic void testDelete(){template.deleteIndex("itzhengitem");}
}

在这里插入图片描述
运行成功
在这里插入图片描述

2、通过Kabina查看

GET itzhengitem

返回结果

{"error" : {"root_cause" : [{"type" : "index_not_found_exception","reason" : "no such index [itzhengitem]","resource.type" : "index_or_alias","resource.id" : "itzhengitem","index_uuid" : "_na_","index" : "itzhengitem"}],"type" : "index_not_found_exception","reason" : "no such index [itzhengitem]","resource.type" : "index_or_alias","resource.id" : "itzhengitem","index_uuid" : "_na_","index" : "itzhengitem"},"status" : 404
}

为了方便我们需要再次创建刚刚的索引
在这里插入图片描述

四、Repository文档操作

Spring Data 的强大之处,就在于你不用写任何DAO处理,自动根据方法名或类的信息进行CRUD操作。

只要你定义一个接口,然后继承Repository提供的一些子接口,就能具备各种基本的CRUD功能。

我们只需要定义接口,然后继承它就OK了。

定义一个接口
在这里插入图片描述

package com.itzheng.es.repository;import com.itzheng.es.pojo.Item;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;public interface ItemRepository extends ElasticsearchRepository<Item,Long> {
//上述泛型的第一个参数的实体类类型,第二个是主键ID类型}

1、新增文档

(1)首先注入

在这里插入图片描述

@Autowiredprivate ItemRepository repository;

(2)编写测试方法

在这里插入图片描述

@Testpublic void insertIndex(){Item item = new Item(1L, "小米手机7", " 手机", "小米", 3499.00, "http://image.leyou.com/13123.jpg");repository.save(item);}

(3)运行测试方法

在这里插入图片描述
在这里插入图片描述

(4)通过Kabina查看

GET itzhengitem/_search
{"took" : 0,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 1,"relation" : "eq"},"max_score" : 1.0,"hits" : [{"_index" : "itzhengitem","_type" : "item","_id" : "1","_score" : 1.0,"_source" : {"id" : 1,"title" : "小米手机7","category" : " 手机","brand" : "小米","price" : 3499.0,"images" : "http://image.leyou.com/13123.jpg"}}]}
}

在这里插入图片描述

2、批量新增

在这里插入图片描述

@Testpublic void indexList(){List<Item> list = new ArrayList<>();list.add(new Item(2L, "坚果手机R1", " 手机", "锤子", 3699.00, "http://image.leyou.com/123.jpg"));list.add(new Item(3L, "华为META10", " 手机", "华为", 4499.00, "http://image.leyou.com/3.jpg"));repository.saveAll(list);}

运行测试
在这里插入图片描述
运行成功
在这里插入图片描述
通过Kabina查看

GET itzhengitem/_search
{"took" : 0,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 3,"relation" : "eq"},"max_score" : 1.0,"hits" : [{"_index" : "itzhengitem","_type" : "item","_id" : "1","_score" : 1.0,"_source" : {"id" : 1,"title" : "小米手机7","category" : " 手机","brand" : "小米","price" : 3499.0,"images" : "http://image.leyou.com/13123.jpg"}},{"_index" : "itzhengitem","_type" : "item","_id" : "2","_score" : 1.0,"_source" : {"id" : 2,"title" : "坚果手机R1","category" : " 手机","brand" : "锤子","price" : 3699.0,"images" : "http://image.leyou.com/123.jpg"}},{"_index" : "itzhengitem","_type" : "item","_id" : "3","_score" : 1.0,"_source" : {"id" : 3,"title" : "华为META10","category" : " 手机","brand" : "华为","price" : 4499.0,"images" : "http://image.leyou.com/3.jpg"}}]}
}

多新增几条数据

@Testpublic void indexList(){List<Item> list = new ArrayList<>();list.add(new Item(4L, "小米手机7", "手机", "小米", 3299.00, "http://image.leyou.com/13123.jpg"));list.add(new Item(5L, "坚果手机R1", "手机", "锤子", 3699.00, "http://image.leyou.com/13123.jpg"));list.add(new Item(6L, "华为META10", "手机", "华为", 4499.00, "http://image.leyou.com/13123.jpg"));list.add(new Item(7L, "小米Mix2S", "手机", "小米", 4299.00, "http://image.leyou.com/13123.jpg"));list.add(new Item(8L, "荣耀V10", "手机", "华为", 2799.00, "http://image.leyou.com/13123.jpg"));repository.saveAll(list);}

3、修改文档

修改和新增是同一个接口,区分的依据就是id

这一点跟我们在页面发起PUT请求是类似的。

修改id为1 的数据
在这里插入图片描述

@Testpublic void updateIndex(){Item item = new Item(1L, "大米手机7", " 手机", "小米", 3499.00, "http://image.leyou.com/13123.jpg");repository.save(item);}

在这里插入图片描述
通过Kabina查看

GET itzhengitem/_search

在这里插入图片描述

4、基本查询

ElasticsearchRepository提供了一些基本的查询方法:

(1)通过id查询

在这里插入图片描述

@Testpublic void testQuery(){Optional<Item> optional = this.repository.findById(1L);System.out.println(optional.get());}

在这里插入图片描述
在这里插入图片描述

(2)查询所有

在这里插入图片描述

  @Testpublic void testFind(){Iterable<Item> items = repository.findAll();for (Item item : items) {System.out.println(item);}}

在这里插入图片描述
运行结果
在这里插入图片描述

(3) 自定义方法

Spring Data 的另一个强大功能,是根据方法名称自动实现功能。

比如:你的方法名叫做:findByTitle,那么它就知道你是根据title查询,然后自动帮你完成,无需写实现类。

当然,方法名称要符合一定的约定:

KeywordSampleElasticsearch Query String
AndfindByNameAndPrice{"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
OrfindByNameOrPrice{"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
IsfindByName{"bool" : {"must" : {"field" : {"name" : "?"}}}}
NotfindByNameNot{"bool" : {"must_not" : {"field" : {"name" : "?"}}}}
BetweenfindByPriceBetween{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
LessThanEqualfindByPriceLessThan{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
GreaterThanEqualfindByPriceGreaterThan{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
BeforefindByPriceBefore{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
AfterfindByPriceAfter{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
LikefindByNameLike{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
StartingWithfindByNameStartingWith{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
EndingWithfindByNameEndingWith{"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}}
Contains/ContainingfindByNameContaining{"bool" : {"must" : {"field" : {"name" : {"query" : "**?**","analyze_wildcard" : true}}}}}
InfindByNameIn(Collection<String>names){"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}
NotInfindByNameNotIn(Collection<String>names){"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}}
NearfindByStoreNearNot Supported Yet !
TruefindByAvailableTrue{"bool" : {"must" : {"field" : {"available" : true}}}}
FalsefindByAvailableFalse{"bool" : {"must" : {"field" : {"available" : false}}}}
OrderByfindByAvailableTrueOrderByNameDesc{"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}}

例如,我们来按照价格区间查询,定义这样的一个方法:

1)在接口当中定义

在这里插入图片描述

package com.itzheng.es.repository;import com.itzheng.es.pojo.Item;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;import java.util.List;public interface ItemRepository extends ElasticsearchRepository<Item,Long> {
//上述泛型的第一个参数的实体类类型,第二个是主键ID类型List<Item> findByPriceBetween(double price1, double price2);}
2)在EsTest编写queryByPriceBetween方法(通过价格的范围查询)

不需要写实现类,然后我们直接去运行:
在这里插入图片描述

@Testpublic void queryByPriceBetween(){List<Item> items = repository.findByPriceBetween(2000, 4000);for (Item item : items) {System.out.println(item);}}

在这里插入图片描述
在这里插入图片描述

5、高级查询

(1)基本查询

先看看基本玩法
在这里插入图片描述

@Testpublic void testQueryCustom(){//词条查询MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("title", "小米");Iterable<Item> items = repository.search(queryBuilder);items.forEach(System.out::println);}

QueryBuilders提供了大量的静态方法,用于生成各种不同类型的查询对象,例如:词条、模糊、通配符等QueryBuilder对象。

结果:
在这里插入图片描述

(2)自定义查询

先来看最基本的match query:
在这里插入图片描述

@Testpublic void testNativeQuery(){NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();//结果过滤//添加查询条件queryBuilder.withQuery(QueryBuilders.matchQuery("title","小米"));NativeSearchQuery searchQuery = queryBuilder.build();//执行搜索,获取结果Page<Item> result = repository.search(searchQuery);//打印总条数System.out.println(result.getTotalElements());//打印总页数System.out.println(result.getTotalPages());result.forEach(System.out::println);}

NativeSearchQueryBuilder:Spring提供的一个查询条件构建器,帮助构建json格式的请求体

Page<item>:默认是分页查询,因此返回的是一个分页的结果对象,包含属性:

  • totalElements:总条数
  • totalPages:总页数
  • Iterator:迭代器,本身实现了Iterator接口,因此可直接迭代得到当前页的数据

返回结果
在这里插入图片描述

(3)分页查询和排序

利用NativeSearchQueryBuilder可以方便的实现分页:

需要再添加一些数据方便测试

@Testpublic void indexList(){List<Item> list = new ArrayList<>();list.add(new Item(9L, "小米手机7", "手机", "小米", 3299.00, "http://image.leyou.com/13123.jpg"));list.add(new Item(10L, "坚果手机R1", "手机", "锤子", 3699.00, "http://image.leyou.com/13123.jpg"));list.add(new Item(11L, "华为META10", "手机", "华为", 4499.00, "http://image.leyou.com/13123.jpg"));list.add(new Item(12L, "小米Mix2S", "手机", "小米", 4299.00, "http://image.leyou.com/13123.jpg"));list.add(new Item(13L, "荣耀V10", "手机", "华为", 2799.00, "http://image.leyou.com/13123.jpg"));repository.saveAll(list);}

再次测试
在这里插入图片描述

  @Testpublic void testNativeQuery(){// 构建查询条件NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();// 添加基本的分词查询queryBuilder.withQuery(QueryBuilders.termQuery("title", "手机"));// 初始化分页参数int page = 0;int size = 3;// 设置分页参数queryBuilder.withPageable(PageRequest.of(page, size));// 执行搜索,获取结果Page<Item> items = this.repository.search(queryBuilder.build());// 打印总条数System.out.println(items.getTotalElements());// 打印总页数System.out.println(items.getTotalPages());// 每页大小System.out.println(items.getSize());// 当前页System.out.println(items.getNumber());items.forEach(System.out::println);}

在这里插入图片描述
修改起始页
在这里插入图片描述

@Testpublic void testNativeQuery(){// 构建查询条件NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();// 添加基本的分词查询queryBuilder.withQuery(QueryBuilders.termQuery("title", "手机"));// 初始化分页参数int page = 1;int size = 3;// 设置分页参数queryBuilder.withPageable(PageRequest.of(page, size));// 执行搜索,获取结果Page<Item> items = this.repository.search(queryBuilder.build());// 打印总条数System.out.println("总条数"+items.getTotalElements());// 打印总页数System.out.println("总页数"+items.getTotalPages());// 每页大小System.out.println("每页大小"+items.getSize());// 当前页System.out.println(items.getNumber());items.forEach(System.out::println);}

在这里插入图片描述
1是当前页

6、聚合

(1)聚合为桶

桶就是分组,比如这里我们按照品牌brand进行分组:

在这里插入图片描述

    @Testpublic void testAgg(){NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();String aggName = "popularBrand";//聚合// AggregationBuilders.terms("popularBrand").field("brand")// terms聚合类型(查询关键字)  popularBrand聚合名称  brand聚合字段queryBuilder.addAggregation(AggregationBuilders.terms(aggName).field("brand"));//查询并返回带聚合结果AggregatedPage<Item> result = template.queryForPage(queryBuilder.build(), Item.class);//解析聚合Aggregations aggs = result.getAggregations();//得到了当前查询的JSON集合//获取指定名称的聚合StringTerms terms = aggs.get(aggName);//获取桶List<StringTerms.Bucket> buckets = terms.getBuckets();for (StringTerms.Bucket bucket : buckets) {System.out.println("bucket.getKeyAsString() = "+bucket.getKeyAsString());System.out.println("bucket.getDocCount() = "+bucket.getDocCount());}}

结果
在这里插入图片描述

在这里插入图片描述

(2)嵌套聚合,求平均值

在这里插入图片描述

@Testpublic void testSubAgg(){NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();// 不查询任何结果queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));// 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brandqueryBuilder.addAggregation(AggregationBuilders.terms("brands").field("brand").subAggregation(AggregationBuilders.avg("priceAvg").field("price")) // 在品牌聚合桶内进行嵌套聚合,求平均值);// 2、查询,需要把结果强转为AggregatedPage类型AggregatedPage<Item> aggPage = (AggregatedPage<Item>) this.repository.search(queryBuilder.build());// 3、解析// 3.1、从结果中取出名为brands的那个聚合,// 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型StringTerms agg = (StringTerms) aggPage.getAggregation("brands");// 3.2、获取桶List<StringTerms.Bucket> buckets = agg.getBuckets();// 3.3、遍历for (StringTerms.Bucket bucket : buckets) {// 3.4、获取桶中的key,即品牌名称  3.5、获取桶中的文档数量System.out.println(bucket.getKeyAsString() + ",共" + bucket.getDocCount() + "台");// 3.6.获取子聚合结果:InternalAvg avg = (InternalAvg) bucket.getAggregations().asMap().get("priceAvg");System.out.println("平均售价:" + avg.getValue());}}

在这里插入图片描述


http://chatgpt.dhexx.cn/article/QM3hhpvd.shtml

相关文章

【Elasticsearch】整合Spring Data Elasticsearch

整合Spring Data Elasticsearch 如何查看官方文档&#xff08;了解&#xff09; 官方文档&#xff1a;Java High Level REST Client | Java REST Client [6.8] | Elastic 下面是获得文档的方式&#xff08;可以不用看&#xff09;&#xff1a; 步骤一&#xff1a;查询“文档…

ElasticSearch高级篇

注&#xff1a;该文档是网上资源&#xff0c;该文档通俗易懂&#xff0c;我已经按照文档学习完了&#xff0c;后期我会加入自己的实践内容。 0.学习目标 独立安装Elasticsearch会使用Rest的API操作索引会使用Rest的API查询数据会使用Rest的API聚合数据掌握Spring Data Elastics…

自己挖坑自己填 spring-data-elasticsearch 4.0.0.M4 简单实践

前几天安装了elasticsearch7.6.1,今天准备实践下spring-data-elasticsearch,没想到4.0改动大资料少,全靠官方文档撑着 文章目录 搭建环境编写yml配置创建实体类 基于Spring Data的CRUD直接从方法名称派生查询自定义的查询 ElasticsearchRestTemplate的使用indexOperations 索引…

Elasticsearch集群,java操作es

今日内容 集群和分布式Elasticsearch集群Elasticsearch客户端 java代码取操作ES有三种方式 1、es提供的原生的操作方式 在es 8.0后会移除 2、es提供的rest风格的操作方式 3、SpringDataElasticSearch的方式 第一章 集群和分布式 集群和分布式的概念有联系也有区别&#xff0c;我…

数据结构(Java)-排序算法-插入排序

插入排序法思想: 插入排序的基本思想是&#xff1a;把n个待排序的元素看成为一个有序表和一个无序表&#xff0c;开始时有序表中只包含一个元素&#xff0c;无序表中包含有n-1个元素&#xff0c;排序过程中每次从无序表中取出第一个元素&#xff0c;把它依次与有序表元素进行比…

ES基础篇-11-Spring提供的elasticsearch组件:Spring Data Elasticsearch

1. 简介 1.1.什么是SpringDataElasticsearch SpringDataElasticsearch&#xff08;以后简称SDE&#xff09;是Spring Data项目下的一个子模块。 查看 Spring Data的官网&#xff1a;http://projects.spring.io/spring-data/ Spring Data 的使命是给各种数据访问提供统一的编…

91-Lucene+ElasticSeach核心技术

LuceneElasticSeach 什么是全文检索&#xff1a; 数据分类&#xff1a; 我们生活中的数据总体分为两种&#xff1a;结构化数据和非结构化数据 结构化数据&#xff1a;指具有固定格式或有限长度的数据&#xff0c;如数据库&#xff0c;元数据等 非结构化数据&#xff1a;指…

SpringBoot集成Elasticseach

目录 一、Elasticseach介绍 1.简单介绍 2.对比关系&#xff1a; 3.详细说明&#xff1a; 4.查出数据的解释 二、SpringBoot集成Elasticseach 1.引入依赖 2.添加配置 3.创建pojo类与索引对应 4.SpringData封装了基础的增删改查&#xff0c;自定义增删改查 5.测试方法-…

Windows系统下载安装MinGW(包括32位和64位)

一、MinGW简介 MinGW是是将GCC编译器和GNU Binutils移植到Win32平台下的产物&#xff0c;包括一系列头文件&#xff08;Win32API&#xff09;、库和可执行文件。MinGW是从Cygwin&#xff08;1.3.3版&#xff09;基础上发展而来。GCC支持的语言大多在MinGW也受支持&#xff0c;其…

MySQL寻找特定字符后的字符串

“日边清梦断,镜里朱颜改” 在操作数据库的某些情况下,我们需要对其中一字段的最后几个字做修改,如下图,把老师改为学生 我找了半天,好像没找到mysql中有合适的函数,能找到最后一个/符号并且修改后面的字符串.需要用好几个函数嵌套使用.如下: select 处理前 as status,org…

支付宝支付功能的实现

支付宝支付功能实现 一.环境准备 二.配置沙箱环境 1.浏览器搜索 支付宝开放平台 2.找到开发服务&#xff0c;选择沙箱 3.根据文档提示&#xff0c;一步步配置 4.配置完成后的样子 5.下载好支付宝手机开放平台助手&#xff0c;可以获取应用私钥 **注意&#xff1a;**应用公…

针对Spring/Gradle启动失败的一些通用解决方案

文章目录 0 前言1 更改Gradle JVM的Java JDK1.1 执行JUnit测试时&#xff0c;Gradle报错 0 前言 当你对Spring/Gradle启动失败的错误信息一筹莫展时&#xff0c;不妨试试以下这些通用的解决方案 1 更改Gradle JVM的Java JDK Settings -> Build, Execution, Deployment -&…

13123

111 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个注脚注释也是必不…

编译JSqlparser

这个东西是用来解析sql的。既然要编译源码&#xff0c;第一步当然要下载源码了。 要下源码当然是到世界最大同志网站了: https://github.com/JSQLParser/JSqlParser 项目导入idea&#xff0c;缺少源码&#xff0c;原来需要javacc来生成代码。 自然我们需要安装javacc这个东西&…

jsqlparser:修改语法定义(JSqlParserCC.jjt)实现UPSERT支持Phoenix语法ON DUPLICATE KEY IGNORE

最近在用jsqlparser4.5解析SQL时遇到了一个问题&#xff0c; 如下是apache phoenix的UPSERT语句 UPSERT INTO TEST (ID, COUNTER) VALUES (123, 0) ON DUPLICATE KEY IGNOREON DUPLICATE KEY IGNORE即为当主键重复时忽略&#xff0c;这与MySQL的IGNORE语法不同&#xff1a; …

jsqlparser mysql_java sql解析器比较druid sql parser vs jsqlparser vs fdb-sql-parser

先上结论。 功能上&#xff1a;druid sql parser(支持分区、WITH、DUAL等。使用mysql语法解析时&#xff0c;已知oracle的一些操作符会被转为mysql&#xff0c;如|| 转为OR。使用oracle解析器时&#xff0c;union all里面的括号会被移到外面&#xff0c;从而导致可能执行出错) …

JSqlParser4.3版本无法解析mysql中JSON_OBJECT函数抛出ParseException异常

2022年3月31日&#xff0c;找了一下午的bug bug 已经提交issues&#xff0c;详情请看GitHub&#xff0c;地址&#xff1a;https://github.com/JSQLParser/JSqlParser/issues/1504 使用JSqlparser4.3版作者提供的补丁版后解决&#xff0c;下载地址&#xff1a;https://download.…

JSqlparser 使用攻略(高效的SQL解析工具)

JSqlparser github地址 目录 Maven 引用远程仓库依赖包 SQL解析获取SQL中的信息创建Select的方式创建Select&#xff08;非SQL String 创建&#xff09; Insert 插入字段和值where条件中字段替换解析SQL例子获取所有tableNames自动生成别名SQL函数单表where条件拼装JOIN 拼装 校…

jsqlparser 简介、中文文档、中英对照文档 下载

jsqlparser 文档 下载链接&#xff08;含jar包、源码、pom&#xff09; 组件名称中文-文档-下载链接中英对照-文档-下载链接jsqlparser-0.9.5.jarjsqlparser-0.9.5-API文档-中文版.zipjsqlparser-0.9.5-API文档-中英对照版.zipjsqlparser-1.0.jarjsqlparser-1.0-API文档-中文版…

java使用jsqlparser实现自定义转换

jsqlparser描述&#xff1a; JSqlParser 解析 SQL 语句并将其转换为 Java 类的层次结构。基本上的sql关键字和函数都可以被jsqlparser解析成对象层层包装。 实现的功能&#xff1a; 基础sql查询&#xff0c;条件查询&#xff0c;字段和表得别名&#xff0c;排序&#xff0c;…