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

article/2025/10/5 2:03:34

前几天安装了elasticsearch7.6.1,今天准备实践下spring-data-elasticsearch,没想到4.0改动大资料少,全靠官方文档撑着

文章目录

    • 搭建环境
      • 编写yml配置
      • 创建实体类
    • 基于Spring Data的CRUD
      • 直接从方法名称派生查询
      • 自定义的查询
    • ElasticsearchRestTemplate的使用
      • indexOperations 索引库相关操作
      • 有关Query的构造器
      • QueryBuilders构造复杂查询条件
      • DocumentOperations文档相关操作
      • SearchOperations查询相关操作
        • 基本查询
        • 排序分页查询
        • 聚合查询
        • 嵌套聚合查询
    • 测试类代码集合


搭建环境

进入spring官网,了解一下spring-data-elasticsearch版本
在这里插入图片描述
从上面可以看到,目前版本为3.2.5,但是点进去看后发现,这个版本并不适用于elasticsearch7.6.1,而适用于6.8.6.
在这里插入图片描述
而我们真正需要使用的是spring-data-elasticsearch4.0以上spring boot2.3以上
所以在maven中的pom要导入如下依赖

	<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.0.M3</version><relativePath/> <!-- lookup parent from repository --></parent><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><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>

编写yml配置

在这里插入图片描述配置es

#配置es
spring:elasticsearch:rest:uris: 192.168.231.128:9200 #配置节点地址数组application:name: search-service

上面给出的节点地址配置和旧版本的配置可能有所不同,我用网上的如下配置方式,无法成功启动spring-data-elasticsearch
在这里插入图片描述
下面为部分可以进行的配置选项
在这里插入图片描述

创建实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "goods",shards = 1,replicas = 0)
public class Item implements Serializable {@IdLong id;@Field(type = FieldType.Text,analyzer = "ik_max_word")String title;@Field(type = FieldType.Keyword)String category;@Field(type = FieldType.Keyword)String brand;@Field(type = FieldType.Double)Double price;@Field(type = FieldType.Keyword,index = false)//不会对图片地址查询,指定为falseString images;
}

可以注意到有关实体类的注释:

  • 为需要使用索引库的实体类加上注解 @Document 部分属性如下
    • indexName="索引库名"
    • shards = 分片数量(默认1)
    • replicas = 副本数量(默认1)
  • 为id属性 添加 @Id 注释
  • 各个字段加上注解并制定类型 @Field 部分属性如下
    • type= FieldType.枚举 指定字段类型 Keyword不分词, Text分词 下面为可选类型,对应着elasticsearch的字段类型
      在这里插入图片描述
    • 为需要分词的字段添加分词器 analyzer="分词器名" (ik分词器固定写法 ik_max_word )
    • 是否创建索引 index=boolean(默认true) 例如样例中的图片地址不需要创建索引

基于Spring Data的CRUD

自定义接口继承ElasticsearchRepository<类名,id类型>

public interface ItemRepository extends ElasticsearchRepository<Item,Long> {
}

下面通过文档可以发现两种建立查询的方式:
在这里插入图片描述

直接从方法名称派生查询

ElasticsearchRepository的父类已经写好了部分原生查询,这里有部分已被弃用的查询方法(例如:search)就不演示了
编写测试类
注意: 测试之前要保证你的es中已经存在相应的索引库

@SpringBootTest
class EsDemoApplicationTests {//注入jpa查询@Autowiredprivate ItemRepository itemRepository;@Testpublic void testSaveAll2() {List<Item> list = new ArrayList<>();list.add(new Item(1L,"OPPOFindX2","手机","OPPO",4999d,"http://image.leyou.com/13123.jpg"));list.add(new Item(2L,"OPPOFindX","手机","OPPO",3999d,"http://image.leyou.com/13123.jpg"));list.add(new Item(3L,"OPPORENO","手机","OPPO",2999d,"http://image.leyou.com/13123.jpg"));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"));itemRepository.saveAll(list);Iterable<Item> all = itemRepository.findAll();all.forEach(System.out::println);}
}

saveAll():通过传入对象列表的方式保存多个文档
findAll():查询索引库中所有文档

还有部分find,delete相关方法就不演示了

可以发现单单ElasticsearchRepository的方法是非常少的,无法满足我们的需求
但spring data会根据方法名称自动实现功能。
比如:你的方法名叫做:findByTitle,那么它就知道你是根据title查询,然后自动帮你完成,无需写实现类。
例如: 向接口中自定义两个方法

public interface ItemRepository extends ElasticsearchRepository<Item,Long> {/*** 不需要实现*/List<Item> findByTitle(String title);/*** 范围查item* @param left* @param right* @return*/List<Item> findByPriceBetween(Double left,Double right);
}

其中提供了大量的自定义模板供我们使用
在这里插入图片描述在这里插入图片描述
方法的返回值也可以为stream流对象
在这里插入图片描述
返回stream,有利于我们对返回数据进一步的操作
返回类型也可以是其他集合类型

自定义的查询

例:

	/*** match查询并设置operator* @param title* @param operator* @return*/@Query("{\"match\": {\"title\":{ \"query\": \"?0\",\"operator\":\"?1\"}}}")Item findByTitleOperator(String title,String operator);

自定义查询: 在@Query中写出你的查询json,占位符?0?1是方法的参数
调用方式与上一种一样,但是可以发现手写json还是非常麻烦的


ElasticsearchRestTemplate的使用

在这里插入图片描述在这里插入图片描述在这里插入图片描述我们可以发现ElasticsearchRestTemplate使用高级REST客户端,继承了增删改查接口,其中还有创建HTTP请求的工厂对象

indexOperations 索引库相关操作

下面使用ElasticsearchRestTemplate对象indexOps方法,创建indexOperations的实现类对象并创建索引库

  1. 注入ElasticsearchRestTemplate
  2. 设置索引信息indexOps()传入类的字节码文件,返回IndexOperations接口的实现DefaultIndexOperations,这个类实现了索引的CRUD与http请求
    在这里插入图片描述
  3. create() 创建索引库
  4. indexOperations.createMapping() 创建映射
  5. indexOperations.putMapping(mapping); 将创建的映射写入索引库
@SpringBootTest
class EsDemoApplicationTests {@Autowiredprivate ElasticsearchRestTemplate elasticsearchRestTemplate/*** 创建索引库*/@Testvoid textIndex() {//设置索引信息(绑定实体类)  返回IndexOperationsIndexOperations indexOperations = elasticsearchRestTemplate.indexOps(Item.class);//创建索引库indexOperations.create();//Creates the index mapping for the entity this IndexOperations is bound to.//为该IndexOperations绑定到的实体创建索引映射。  有一个为给定类创建索引的重载,需要类的字节码文件Document mapping = indexOperations.createMapping();//writes a mapping to the index  将刚刚通过类创建的映射写入索引indexOperations.putMapping(mapping);}
}

通过indexOperations还能判断索引库是否存在,删除索引库等等

有关Query的构造器

经过查看结构发现Query接口有一个抽象实现和三个实现
在这里插入图片描述
那我们在使用时真的要new NativeSearchQuery()吗?
在这里插入图片描述
可以通过new NativeSearchQueryBuilder()来构建NativeSearchQuery对象
NativeSearchQuery中有众多的方法来为我们实现复杂的查询与筛选等操作
其中的build()返回NativeSearchQuery,所以,在众多的筛选条件之后别忘了加上build()
在这里插入图片描述
例如查询withQuery,过滤withFilter,排序withSort等等符合es语法的操作

QueryBuilders构造复杂查询条件

在这里插入图片描述
我们需要在这里传入一个QueryBuilder,可以用QueryBuilders构造QueryBuilder对象
在这里插入图片描述下面的查询实现,对应了es的各种查询
在这里插入图片描述

NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", "OPPOFindX");
NativeSearchQuery query = nativeSearchQueryBuilder.withQuery(matchQueryBuilder).build();

DocumentOperations文档相关操作

delete()删除文档
在这里插入图片描述

  • 其中IndexCoordinates为封装索引库名称的不可变值对象, 用IndexCoordinates.of("索引库名")来构造该对象
  • 前4个重载返回的是影响条数String型,注意传入的id也是String
@Test
void testDelete1(){String count = elasticsearchRestTemplate.delete(1 + "", IndexCoordinates.of("goods"));System.out.println(count);
}
  • 最后一个重载传入上面提到的 Query对象 , 索引类的字节码 , 索引库对象
    @Testvoid testDelete2(){elasticsearchRestTemplate.delete(new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("title", "OPPOFindX")).build(),Item.class,IndexCoordinates.of("goods"));SearchHits<Item> search = elasticsearchRestTemplate.search(new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery()).build(), Item.class);search.forEach(System.out::println);}

save()保存/新增文档
在这里插入图片描述save()新增/更新方法:可以传入集合,单个或者多个实体类对象,返回更新后的对象或者集合

    @Testvoid testSaveRest(){List<Item> list = new ArrayList<>();list.add(new Item(1L,"OPPOFindX2","手机","OPPO",4999d,"http://image.leyou.com/13123.jpg"));list.add(new Item(2L,"OPPOFindX","手机","OPPO",3999d,"http://image.leyou.com/13123.jpg"));list.add(new Item(3L,"OPPORENO","手机","OPPO",2999d,"http://image.leyou.com/13123.jpg"));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"));Iterable<Item> save = elasticsearchRestTemplate.save(list);save.forEach(System.out::println);}

SearchOperations查询相关操作

与DocumentOperations中的部分查询方法不同的是,SearchOperations返回的是下面两个对象
在这里插入图片描述
这两个对象应该是4.0新增的,两个对象也很好理解
在这里插入图片描述
search()返回元数据
在这里插入图片描述

基本查询

	@Testvoid testSearch1() {//利用构造器建造NativeSearchQuery  他可以添加条件,过滤,等复杂操作NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("title", "OPPOFindX")).build();//elasticsearchRestTemplate.search方法参数一,本机查询的构造,参数二index的类,可选参数三再次声明库名(可以多个)SearchHits<Item> search = elasticsearchRestTemplate.search(query, Item.class);search.forEach(searchHit-> System.out.println(searchHit.getContent()));}

排序分页查询

SortBuilders.fieldSort("排序字段").order(SortOrder.ASC/DESC) : 分页后的排序
PageRequest.of(当前页,每页条数): 注意起始页为0

	@Testvoid testNativeSearchQueryBuilder2() {NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("category", "手机"))//添加分页  注意页码是从0开始的//pageable的实现类PageRequest的静态方法of//要排序就增加参数3 Sort.Direction.ASC升  Sort.Direction.DESC降.withPageable(PageRequest.of(1,4))//排序整体//根据字段排序fieldSort("字段名")   .order(SortOrder.ASC/DESC).withSort(SortBuilders.fieldSort("price").order(SortOrder.ASC)).build();//elasticsearchRestTemplate.search方法参数一,本机查询的构造,参数二index的类,可选参数三再次声明库名(可以多个)SearchHits<Item> search = elasticsearchRestTemplate.search(query, Item.class);search.forEach(searchHit-> System.out.println(searchHit.getContent()));}

聚合查询

下面聚合查各品牌的产品数量:
AggregationBuilders来建立聚合对象,可选多种聚合方式
 例如字段聚合:terms中放聚合名,field中放聚合字段
getAggregations()从searchHits中获取聚合结果,聚合结果为Map,键为聚合名,值为聚合结果

@Testvoid testAgg1(){NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();//聚合可以有多个,所以add//terms词条聚合,传入聚合名称   field("聚合字段")   size(结果集大小)NativeSearchQuery query = nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("brands").field("brand"))//结果集过滤  这里设置不需要结果集(不添加包含与不包含,会自动生成length为0数组).withSourceFilter(new FetchSourceFilterBuilder().build()).build();SearchHits<Item> hits = elasticsearchRestTemplate.search(query, Item.class);System.out.println(hits);//获取聚合结果集   因为结果为字符串类型 所以用ParsedStringTerms接收   还有ParsedLongTerms接收数字  ParsedDoubleTerms接收小数Aggregations aggregations = hits.getAggregations();assert aggregations != null;ParsedStringTerms brands = aggregations.get("brands");//获取桶brands.getBuckets().forEach(bucket->{//获取桶中的key   与    记录数System.out.println(bucket.getKeyAsString()+" "+bucket.getDocCount());});}

在这里插入图片描述
上图为常见的聚合查询结果类,如果无法找到可以通过sout的方式打印出类型

嵌套聚合查询

下面查出各品牌的产品数量后再查出各品牌产品均价:
添加子聚合 subAggregation(添加方式和上面是一样的)
获取自聚合 在父聚合的桶中用getAggregations()获取子聚合

	@Testvoid testAgg2(){NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();//聚合可以有多个,所以add//terms词条聚合,传入聚合名称   field("聚合字段")NativeSearchQuery query = nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("brands").field("brand")//添加子聚合  subAggregation(添加方式是一样的)  值为桶中品牌均价.subAggregation(AggregationBuilders.avg("price_avg").field("price")))//结果集过滤  这里设置不需要结果集(不添加包含与不包含,会自动生成长为0数组).withSourceFilter(new FetchSourceFilterBuilder().build()).build();SearchHits<Item> hits = elasticsearchRestTemplate.search(query, Item.class);System.out.println(hits);//获取聚合结果集   因为结果为字符串类型 所以用ParsedStringTerms接收   还有ParsedLongTerms接收数字  ParsedDoubleTerms接收小数Aggregations aggregations = hits.getAggregations();assert aggregations != null;ParsedStringTerms brands = aggregations.get("brands");//获取桶brandsbrands.getBuckets().forEach(bucket->{//获取桶中的key   与    记录数System.out.println(bucket.getKeyAsString()+" "+bucket.getDocCount());//获取嵌套的桶price_avgParsedAvg price_avg = bucket.getAggregations().get("price_avg");System.out.println(price_avg.getValue());});}

测试类代码集合

@SpringBootTestclass EsDemoApplicationTests {//是使用高级REST客户端的ElasticsearchOperations接口的实现。@Autowiredprivate ElasticsearchRestTemplate elasticsearchRestTemplate;//注入jpa查询@Autowiredprivate ItemRepository itemRepository;/*** 创建索引库* indexOps返回了DefaultIndexOperations基于高级代理实现了IndexOperations接口*/@Testvoid textIndex() {//设置索引信息(绑定实体类)  返回IndexOperationsIndexOperations indexOperations = elasticsearchRestTemplate.indexOps(Item.class);//创建索引库indexOperations.create();//Creates the index mapping for the entity this IndexOperations is bound to.//为该IndexOperations绑定到的实体创建索引映射。  有一个为给定类创建索引的重载,需要类的字节码文件//返回创建的索引Document mapping = indexOperations.createMapping();System.out.println(mapping);//writes a mapping to the index//将刚刚通过类创建的映射写入索引indexOperations.putMapping(mapping);//delete()//Deletes the index this IndexOperations is bound to//exists() Checks if the index this IndexOperations is bound to exists}/*** save方法进行数据的新增,和修改  有相同id就是修改,无相同id就是新增*/@Testvoid testSave() {Item item=new Item(1L,"OPPOFindX2","手机","OPPO",4999d,"http://image.leyou.com/13123.jpg");Item saveItem = itemRepository.save(item);System.out.println(saveItem);Iterable<Item> all = itemRepository.findAll();all.forEach(System.out::println);}@Testvoid test() {Item item = itemRepository.findByTitleOperator("小米手机7","and");System.out.println(item);}/*** saveAll方法进行批量数据的新增,和修改  有相同id就是修改,无相同id就是新增* findAll查所有*/@Testpublic void testSaveAll() {List<Item> list = new ArrayList<>();list.add(new Item(1L,"OPPOFindX2","手机","OPPO",4999d,"http://image.leyou.com/13123.jpg"));list.add(new Item(2L,"OPPOFindX","手机","OPPO",3999d,"http://image.leyou.com/13123.jpg"));list.add(new Item(3L,"OPPORENO","手机","OPPO",2999d,"http://image.leyou.com/13123.jpg"));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"));itemRepository.saveAll(list);Iterable<Item> all = itemRepository.findAll();all.forEach(System.out::println);}/*** delete相关方法删除*//***findById*/@Testvoid testFindById(){Item byId = itemRepository.findById(2L).get();System.out.println(byId);}@Testvoid testFindByTitle() {List<Item> items = itemRepository.findByTitle("OPPOFindX");System.out.println(items);}@Testvoid testFindByPriceBetween() {List<Item> items = itemRepository.findByPriceBetween(1000d, 8000d);items.forEach(System.out::println);}//elasticsearchRestTemplate/*** delete删除文档*/@Testvoid testDelete1(){String count = elasticsearchRestTemplate.delete(1 + "", IndexCoordinates.of("goods"));System.out.println(count);}@Testvoid testDelete2(){elasticsearchRestTemplate.delete(new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("title", "OPPOFindX")).build(),Item.class,IndexCoordinates.of("goods"));SearchHits<Item> search = elasticsearchRestTemplate.search(new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery()).build(), Item.class);search.forEach(System.out::println);}/*** save*/@Testvoid testSaveRest(){List<Item> list = new ArrayList<>();list.add(new Item(1L,"OPPOFindX2","手机","OPPO",4999d,"http://image.leyou.com/13123.jpg"));list.add(new Item(2L,"OPPOFindX","手机","OPPO",3999d,"http://image.leyou.com/13123.jpg"));list.add(new Item(3L,"OPPORENO","手机","OPPO",2999d,"http://image.leyou.com/13123.jpg"));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"));Iterable<Item> save = elasticsearchRestTemplate.save(list);save.forEach(System.out::println);}/*** 采用elasticsearchRestTemplate查询*/@Testvoid testSearch1() {//利用构造器建造NativeSearchQuery  他可以添加条件,过滤,等复杂操作NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("title", "OPPOFindX")).build();//elasticsearchRestTemplate.search方法参数一,本机查询的构造,参数二index的类,可选参数三再次声明库名(可以多个)SearchHits<Item> search = elasticsearchRestTemplate.search(query, Item.class);search.forEach(searchHit-> System.out.println(searchHit.getContent()));}/*** 分页*/@Testvoid testNativeSearchQueryBuilder2() {NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("category", "手机"))//添加分页  注意页码是从0开始的//pageable的实现类PageRequest的静态方法of//要排序就增加参数3 Sort.Direction.ASC升  Sort.Direction.DESC降.withPageable(PageRequest.of(1,4))//排序整体//根据字段排序fieldSort("字段名")   .order(SortOrder.ASC/DESC).withSort(SortBuilders.fieldSort("price").order(SortOrder.ASC)).build();//elasticsearchRestTemplate.search方法参数一,本机查询的构造,参数二index的类,可选参数三再次声明库名(可以多个)SearchHits<Item> search = elasticsearchRestTemplate.search(query, Item.class);search.forEach(searchHit-> System.out.println(searchHit.getContent()));}/*** 聚合  品牌*/@Testvoid testAgg1(){NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();//聚合可以有多个,所以add//terms词条聚合,传入聚合名称   field("聚合字段")   size(结果集大小)NativeSearchQuery query = nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("brands").field("brand"))//结果集过滤  这里设置不需要结果集(不添加包含与不包含,会自动生成长为0数组).withSourceFilter(new FetchSourceFilterBuilder().build()).build();SearchHits<Item> hits = elasticsearchRestTemplate.search(query, Item.class);System.out.println(hits);//获取聚合结果集   因为结果为字符串类型 所以用ParsedStringTerms接收   还有ParsedLongTerms接收数字  ParsedDoubleTerms接收小数Aggregations aggregations = hits.getAggregations();assert aggregations != null;ParsedStringTerms brands = aggregations.get("brands");//获取桶brands.getBuckets().forEach(bucket->{//获取桶中的key   与    记录数System.out.println(bucket.getKeyAsString()+" "+bucket.getDocCount());});}/*** 聚合嵌套  品牌*/@Testvoid testAgg2(){NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();//聚合可以有多个,所以add//terms词条聚合,传入聚合名称   field("聚合字段")NativeSearchQuery query = nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("brands").field("brand")//添加子聚合  subAggregation(添加方式是一样的)  值为桶中品牌均价.subAggregation(AggregationBuilders.avg("price_avg").field("price")))//结果集过滤  这里设置不需要结果集(不添加包含与不包含,会自动生成长为0数组).withSourceFilter(new FetchSourceFilterBuilder().build()).build();SearchHits<Item> hits = elasticsearchRestTemplate.search(query, Item.class);System.out.println(hits);//获取聚合结果集   因为结果为字符串类型 所以用ParsedStringTerms接收   还有ParsedLongTerms接收数字  ParsedDoubleTerms接收小数Aggregations aggregations = hits.getAggregations();assert aggregations != null;ParsedStringTerms brands = aggregations.get("brands");//获取桶brandsbrands.getBuckets().forEach(bucket->{//获取桶中的key   与    记录数System.out.println(bucket.getKeyAsString()+" "+bucket.getDocCount());//获取嵌套的桶price_avgParsedAvg price_avg = bucket.getAggregations().get("price_avg");System.out.println(price_avg.getValue());});}
}

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

相关文章

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;…

JSQLParser碰到的问题

JSQLParser是github上一个开源的项目&#xff0c;专门解析SQL&#xff0c;可以轻松地得到一条SQL的列、表、条件等对象&#xff0c; P.S. https://github.com/JSQLParser/JSqlParser 最近在做一个功能开发的时候&#xff0c;被他困扰了下&#xff0c;从需求来讲&#xff0c;就是…

JSqlParser-SQL解析处理

一、介绍 JSqlParse是一款很精简的sql解析工具&#xff0c;将sql语句转成Java对象。 官网&#xff1a;JSqlParser - Home 用法&#xff1a;可以用于数据权限处理&#xff0c;拦截sql解析改写sql等等。 二、版本 <dependency><groupId>com.github.jsqlparser&l…

JSQLParser 解析复杂SQL 2.0

前言 这段时间&#xff0c;为了开发数据中台项目&#xff0c;我去研究学习了JSQLParser&#xff08;Java中解析SQL语句的工具&#xff09;&#xff0c;并且结合网上资料&#xff0c;写了一个初步的SQL解析工具类... 正文 时隔三天&#xff0c;我又回来了&#xff0c; 因为之前J…