SpringBoot整合ElasticSearch

Java客户端

在Elasticsearch中,为java提供了2种客户端,一种是REST风格的客户端,另一种是Java API的客户端。https://www.elastic.co/guide/...

1.REST客户端
Elasticsearch提供了2种REST客户端,一种是低级客户端,一种是高级客户端。

  • Java Low Level REST Client:官方提供的低级客户端。该客户端通过http来连接Elasticsearch集群。用户在使用该客户端时需要将请求数据手动拼接成Elasticsearch所需JSON格式进行发送,收到响应时同样也需要将返回的JSON数据手动封装成对象。虽然麻烦,不过该客户端兼容所有的Elasticsearch版本。
  • Java High Level REST Client:官方提供的高级客户端。该客户端基于低级客户端实现,它提供了很多便捷的API来解决低级客户端需要手动转换数据格式的问题。

2.构造数据

curl -X POST "http://47.101.129.45:9200/test/house/_bulk?pretty" -H 'Content-Type: application/json' --data-binary '
{"index":{"_index":"test","_type":"house"}}
{"id":"1001","title":"整租 · 南丹大楼 1居室 7500","price":"7500"}
{"index":{"_index":"test","_type":"house"}}
{"id":"1002","title":"陆家嘴板块,精装设计一室一厅,可拎包入住诚意租。","price":"8500"}
{"index":{"_index":"test","_type":"house"}}
{"id":"1003","title":"整租 · 健安坊 1居室 4050","price":"7500"}
{"index":{"_index":"test","_type":"house"}}
{"id":"1004","title":"整租 · 中凯城市之光+视野开阔+景色秀丽+拎包入住","price":"6500"}
{"index":{"_index":"test","_type":"house"}}
{"id":"1005","title":"整租 · 南京西路品质小区 21213三轨交汇配套齐* 拎包入住","price":"6000"}
{"index":{"_index":"test","_type":"house"}}
{"id":"1006","title":"祥康里简约风格 *南户型拎包入住看房随时","price":"7000"}
'

SpringBoot整合ElasticSearch_第1张图片

3.REST低级客户端
1)用IDEA创建SpringBoot工程spring-elasticsearch



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.2.0.RELEASE
         
    
    com.example
    elasticsearch
    0.0.1-SNAPSHOT
    elasticsearch
    Demo project for Spring Boot

    
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        

        
            junit
            junit
            4.12
        
        
            org.elasticsearch.client
            elasticsearch-rest-client
            6.5.4
        
        
            com.fasterxml.jackson.core
            jackson-databind
            2.9.4
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    


2)编写测试

/**
 * REST低级客户端
 */
public class TestElasticSearch {
    private static final ObjectMapper MAPPER = new ObjectMapper();

    private RestClient restClient;

    @Before
    public void init() {
        RestClientBuilder restClientBuilder = RestClient.builder(
                new HttpHost("47.101.129.45", 9200, "http"));
        restClientBuilder.setFailureListener(new RestClient.FailureListener() {
            @Override
            public void onFailure(Node node) {
                System.out.println("出错了 -> " + node);
            }
        });
        this.restClient = restClientBuilder.build();
    }

    @After
    public void after() throws IOException {
        restClient.close();
    }

    /**
     * 查询集群状态
     *
     * @throws IOException
     */
    @Test
    public void testGetInfo() throws IOException {
        Request request = new Request("GET", "/_cluster/state");
        request.addParameter("pretty", "true");
        Response response = this.restClient.performRequest(request);
        System.out.println(response.getStatusLine());
        System.out.println(EntityUtils.toString(response.getEntity()));
    }

    /**
     * 新增数据
     *
     * @throws IOException
     */
    @Test
    public void testCreateData() throws IOException {
        Request request = new Request("POST", "/test/house");
        request.addParameter("pretty", "true");

        Map data = new HashMap<>();
        data.put("id", "2001");
        data.put("title", "张江高科");
        data.put("price", "3500");
        request.setJsonEntity(MAPPER.writeValueAsString(data));
        Response response = this.restClient.performRequest(request);

        System.out.println(response.getStatusLine());
        System.out.println(EntityUtils.toString(response.getEntity()));
    }

    /**
     * 根据id查询数据
     */
    @Test
    public void testQueryData() throws IOException {
        Request request = new Request("GET", "/test/house/3xNNOW4BpJzEX51okOM5");
        request.addParameter("pretty", "true");

        Response response = this.restClient.performRequest(request);
        System.out.println(response.getStatusLine());
        System.out.println(EntityUtils.toString(response.getEntity()));
    }

    /**
     * 搜索数据
     */
    @Test
    public void testSearchData() throws IOException {
        Request request = new Request("POST", "/test/house/_search");
        String searchJson = "{\"query\": {\"match\": {\"title\": \"拎包入住\"}}}";
        request.setJsonEntity(searchJson);
        request.addParameter("pretty", "true");
        Response response = this.restClient.performRequest(request);

        System.out.println(response.getStatusLine());
        System.out.println(EntityUtils.toString(response.getEntity()));
    }
}

从使用中,可以看出,基本和我们使用RESTful api使用几乎是一致的

4.REST高级客户端
pom.xml引入依赖


    org.elasticsearch.client
    elasticsearch-rest-high-level-client
    6.5.4

编写测试

/**
 * REST高级客户端
 */
public class TestRestHighLevel {

    private RestHighLevelClient client;

    @Before
    public void init() {
        RestClientBuilder restClientBuilder = RestClient.builder(
                new HttpHost("47.101.129.45", 9200, "http")
        );

        this.client = new RestHighLevelClient(restClientBuilder);
    }

    @After
    public void after() throws Exception {
        this.client.close();
    }

    /**
     * 新增文档,同步操作
     *
     * @throws Exception
     */
    @Test
    public void testCreate() throws Exception {
        Map data = new HashMap<>();
        data.put("id", "2002");
        data.put("title", "南京西路 拎包入住 一室一厅");
        data.put("price", "4500");

        IndexRequest indexRequest = new IndexRequest("test", "house").source(data);

        IndexResponse indexResponse = this.client.index(indexRequest, RequestOptions.DEFAULT);

        System.out.println(indexResponse);
        System.out.println("id->" + indexResponse.getId());
        System.out.println("index->" + indexResponse.getIndex());
        System.out.println("type->" + indexResponse.getType());
        System.out.println("version->" + indexResponse.getVersion());
        System.out.println("result->" + indexResponse.getResult());
        System.out.println("shardInfo->" + indexResponse.getShardInfo());
    }

    /**
     * 新增文档,异步操作
     */

    @Test
    public void testCreateAsync() throws Exception {
        Map data = new HashMap<>();
        data.put("id", "2003");
        data.put("title", "南京东路最新房源二室一厅");
        data.put("price", "5500");

        IndexRequest indexRequest = new IndexRequest("test", "house").source(data);

        this.client.indexAsync(indexRequest, RequestOptions.DEFAULT, new ActionListener() {
            @Override
            public void onResponse(IndexResponse indexResponse) {
                System.out.println(indexResponse);
            }

            @Override
            public void onFailure(Exception e) {
                System.out.println(e);
            }
        });
        Thread.sleep(2000);
    }

    /**
     * 指定返回字段查询
     */

    @Test
    public void testQuery() throws Exception {
        GetRequest request = new GetRequest("test", "house", "4hN-OW4BpJzEX51oe-Of");

        //指定返回字段
        String[] includes = new String[]{"title", "id"};
        String[] excludes = Strings.EMPTY_ARRAY;

        FetchSourceContext fetchSourceContext = new FetchSourceContext(true, includes, excludes);
        request.fetchSourceContext(fetchSourceContext);

        GetResponse response = this.client.get(request, RequestOptions.DEFAULT);
        System.out.println("数据 -> " + response);
    }

    /**
     * 判断是否存在
     */

    @Test
    public void testExists() throws Exception {
        GetRequest getRequest = new GetRequest("test", "house", "4hN-OW4BpJzEX51oe-Of");
        //不返回字段
        getRequest.fetchSourceContext(new FetchSourceContext(false));
        boolean exists = this.client.exists(getRequest, RequestOptions.DEFAULT);
        System.out.println("exists -> " + exists);
    }

    /**
     * 删除数据
     */
    @Test
    public void testDelete() throws Exception {
        DeleteRequest deleteRequest = new DeleteRequest("test", "house", "4hN-OW4BpJzEX51oe-Of");
        DeleteResponse response = this.client.delete(deleteRequest, RequestOptions.DEFAULT);
        System.out.println(response.status());// OK or NOT_FOUND
    }

    /**
     * 更新数据
     */
    @Test
    public void testUpdate() throws Exception {
        UpdateRequest updateRequest = new UpdateRequest("test", "house", "4BN4OW4BpJzEX51o3-PZ");

        Map data = new HashMap<>();
        data.put("title", "南京西路2 一室一厅2");
        data.put("price", "4000");
        updateRequest.doc(data);
        UpdateResponse response = this.client.update(updateRequest, RequestOptions.DEFAULT);
        System.out.println("version -> " + response.getVersion());
    }

    /**
     * 查询数据
     */
    @Test
    public void testSearch() throws Exception {
        SearchRequest searchRequest = new SearchRequest("test");
        searchRequest.types("house");

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchQuery("title", "拎包入住"));
        sourceBuilder.from(0);
        sourceBuilder.size(5);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(sourceBuilder);

        SearchResponse search = this.client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println("搜索到->" + search.getHits().totalHits + "条数据");

        SearchHits hits = search.getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
    }

}

SpringBoot整合Elasticsearch

Spring Data项目对Elasticsearch做了支持,其目的就是简化对Elasticsearch的操作,https://spring.io/projects/sp...

1.导入依赖



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.2.0.RELEASE
         
    
    com.example
    elasticsearch
    0.0.1-SNAPSHOT
    elasticsearch
    Demo project for Spring Boot

    
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        

        
            junit
            junit
            4.12
        
        
            org.elasticsearch.client
            elasticsearch-rest-client
            6.5.4
        
        
            com.fasterxml.jackson.core
            jackson-databind
            2.9.4
        

        
        
            org.elasticsearch.client
            elasticsearch-rest-high-level-client
            6.5.4
        

        
        
            org.springframework.boot
            spring-boot-starter-data-elasticsearch
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

2.编写application.yml

spring:
  application:
    name: spring-elasticsearch
  data:
    elasticsearch:
      cluster-name: docker-cluster
      cluster-nodes: 47.101.129.45:9300

这里要注意,使用的端口是9300,而并非9200,原因是9200是RESTful端口,9300是API端口。

ElasticSearch之ElasticsearchTemplate

3.编写测试

@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "demo", type = "person", createIndex = false)
public class Person {
    /**
     * 1.索引库(indices)         indices是index的复数,代表许多的索引,
     * 2.类型(type)             类型是模拟mysql中的table概念,一个索引库下可以有不同类型的索引,比如商品索引,订单索引,其数据格式不同。不过这会导致索引库混乱,因此未来版本中会移除这个概念
     * 3.文档(document)         存入索引库原始的数据。比如每一条商品信息,就是一个文档
     * 4.字段(field)             文档中的属性
     * 5.映射配置(mappings)     字段的数据类型、属性、是否索引、是否存储等特性
     */

    /**
     * @Document 作用在类,标记实体类为文档对象,一般有两个属性
     *      1.indexName:对应索引库名称
     *      2.type:对应在索引库中的类型
     *      3.shards:分片数量,默认5
     *      4.replicas:副本数量,默认1
     * @Id 作用在成员变量,标记一个字段作为id主键
     * @Field 作用在成员变量,标记为文档的字段,并指定字段映射属性:
     *      1.type:字段类型,是枚举:FieldType,可以是text、long、short、date、integer、object等
     *      2.text:存储数据时候,会自动分词,并生成索引
     *      3.keyword:存储数据时候,不会分词建立索引
     *      4.Numerical:数值类型,分两类
     *          基本数据类型:long、interger、short、byte、double、float、half_float
     *          浮点数的高精度类型:scaled_float
     *          需要指定一个精度因子,比如10或100。elasticsearch会把真实值乘以这个因子后存储,取出时再还原。
     *      5.Date:日期类型
     *          elasticsearch可以对日期格式化为字符串存储,但是建议我们存储为毫秒值,存储为long,节省空间。
     *      6.index:是否索引,布尔类型,默认是true
     *      7.store:是否存储,布尔类型,默认是false
     *      8.analyzer:分词器名称,这里的ik_max_word即使用ik分词器
     */
    @Id
    private Long id;

    @Field(store = true)
    private String name;

    @Field
    private Integer age;

    @Field
    private String mail;

    @Field(store = true)
    private String hobby;
}

1)新增数据

/**
 * Spring Data ElasticSearch
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestSpringBootES {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    /**
     * 添加数据
     */
    @Test
    public void save() {
        User user = new User();
        user.setId(1001L);
        user.setName("赵柳");
        user.setAge(20);
        user.setHobby("足球、篮球、听音乐");

        IndexQuery indexQuery = new IndexQueryBuilder()
                .withObject(user).build();

        String index = this.elasticsearchTemplate.index(indexQuery);

        System.out.println(index);
    }
}

1.jpg

2)批量插入

@Test
public void testBulk() {
    List list = new ArrayList<>();
    for (int i = 0; i < 5000; i++) {
        User person = new User();
        person.setId(1001L + i);
        person.setAge(i % 50 + 10);
        person.setName("张三" + i);
        person.setHobby("足球、篮球、听音乐");

        IndexQuery indexQuery = new IndexQueryBuilder().withObject(person).build();
        list.add(indexQuery);
    }
    Long start = System.currentTimeMillis();
    this.elasticsearchTemplate.bulkIndex(list);

    System.out.println("用时:" + (System.currentTimeMillis() - start));
}

SpringBoot整合ElasticSearch_第2张图片

3)局部更新,全部更新使用index覆盖即可

@Test
public void testUpdate() {
    IndexRequest indexRequest = new IndexRequest();
    indexRequest.source("age", "30");

    UpdateQuery updateQuery = new UpdateQueryBuilder()
            .withId("1002")
            .withClass(User.class)
            .withIndexRequest(indexRequest).build();

    UpdateResponse response = this.elasticsearchTemplate.update(updateQuery);

    System.out.println(response);

}

4)删除

@Test
public void testDelete() {
    String result = this.elasticsearchTemplate.delete(User.class, "1002");
    System.out.println(result);
}

5)查询

@Test
public void testSearch() {
    PageRequest pageRequest = PageRequest.of(0, 10);//设置分页参数

    SearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withQuery(QueryBuilders.matchQuery("name", "赵柳"))//match查询
            .withPageable(pageRequest)
            .build();

    AggregatedPage persons = this.elasticsearchTemplate.queryForPage(searchQuery, User.class);
    System.out.println("persons ->" + persons);
    System.out.println("总页数:" + persons.getTotalPages()); //获取总页数

    List content = persons.getContent();// 获取搜索到的数据
    for (User p : content) {
        System.out.println(p);
    }
}

SpringBoot整合ElasticSearch_第3张图片

ElasticSearch之ElasticsearchRepository

1.创建实体Pojo

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;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "commodity", type = "docs", shards = 1, replicas = 0)
public class Commodity {
    @Id
    private Long id;

    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String title; //标题

    @Field(type = FieldType.Keyword)
    private String category;// 分类

    @Field(type = FieldType.Keyword)
    private String brand; // 品牌

    @Field(type = FieldType.Double)
    private Double price; // 价格

    @Field(index = false, type = FieldType.Keyword)
    private String images; // 图片地址
}

2.继承ElasticsearchRepository

import com.example.elasticsearch.pojo.Commodity;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.util.List;

public interface CommodityRepository extends ElasticsearchRepository {

}

3.测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestSpringBootES2 {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    
    @Resource
    private CommodityRepository commodityRepository;

    /**
     * 创建索引
     */
    @Test
    public void createIndex() {
        boolean index = elasticsearchTemplate.createIndex(Commodity.class);
        System.out.println(index);
    }
    
    /**
     * 添加数据
     */
    @Test
    public void testInsert() {
        Commodity commodity = new Commodity(1L, "小米手机7", " 手机",
                "小米", 3499.00, "http://image.baidu.com/13123.jpg");
        Commodity save = commodityRepository.save(commodity);
        System.out.println(save);
    }

}

1.jpg

1)批量

@Test
public void testBulk() {
    List list = new ArrayList<>();
    list.add(new Commodity(2L, "坚果手机R1", " 手机", "锤子", 3699.00, "http://image.baidu.com/13123.jpg"));
    list.add(new Commodity(3L, "华为META10", " 手机", "华为", 4499.00, "http://image.baidu.com/13123.jpg"));

    list.add(new Commodity(4L, "小米手机7", "手机", "小米", 3299.00, "http://image.baidu.com/13123.jpg"));
    list.add(new Commodity(5L, "坚果手机R1", "手机", "锤子", 3699.00, "http://image.baidu.com/13123.jpg"));
    list.add(new Commodity(6L, "华为META10", "手机", "华为", 4499.00, "http://image.baidu.com/13123.jpg"));
    list.add(new Commodity(7L, "小米Mix2S", "手机", "小米", 4299.00, "http://image.baidu.com/13123.jpg"));
    list.add(new Commodity(8L, "荣耀V10", "手机", "华为", 2799.00, "http://image.baidu.com/13123.jpg"));

    commodityRepository.saveAll(list);
}

SpringBoot整合ElasticSearch_第4张图片

2.修改

@Test
public void testUpdate() {
    Commodity commodity = new Commodity(1L, "苹果XSMax", " 手机",
            "小米", 3499.00, "http://image.baidu.com/13123.jpg");
    commodityRepository.save(commodity);
}

3.降序、升序

/**
 * 价格的降序、升序查询
 */
@Test
public void testQueryAll() {
    Iterable commodities = commodityRepository.findAll(Sort.by("price").ascending());//降序
    for (Commodity commodity : commodities) {
        System.out.println(commodity);
    }
}

SpringBoot整合ElasticSearch_第5张图片

4.按照价格区间查询
CommodityRepository接口新增findByPriceBetween方法

/**
 * 根据价格区间查询
 *
 * @param price1
 * @param price2
 * @return
 */
List findByPriceBetween(double price1, double price2);
@Test
public void queryByPriceBetween() {
    List list = commodityRepository.findByPriceBetween(2000.00, 3500.00);
    for (Commodity commodity : list) {
        System.out.println("commodity -> " + commodity);
    }
}

1.jpg

5.词条匹配查询

@Test
public void testMatchQuery() {
    // 构建查询条件,在queryBuilder对象中自定义查询
    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    //matchQuery:底层就是使用的termQuery
    queryBuilder.withQuery(QueryBuilders.matchQuery("title", "小米手机"));
    //查询,search默认就是分页查找
    Page commoditys = commodityRepository.search(queryBuilder.build());
    // 总条数
    long total = commoditys.getTotalElements();
    System.out.println("total -> " + total);
    for (Commodity item : commoditys) {
        System.out.println("商品->" + item);
    }
}

1.jpg

/**
 * termQuery:功能更强大,除了匹配字符串以外,还可以匹配 int/long/double/float/....
 */
@Test
public void testTermQuery() {
    NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
    builder.withQuery(QueryBuilders.termQuery("price", 3699));
    // 查找
    Page page = commodityRepository.search(builder.build());

    for (Commodity item : page) {
        System.out.println("商品->" + item);
    }
}

6.bool查詢

@Test
public void testBooleanQuery() {
    NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
    builder.withQuery(
            QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("title", "华为"))
                    .must(QueryBuilders.matchQuery("brand", "华为"))
    );

    // 查找
    Page page = commodityRepository.search(builder.build());
    for (Commodity item : page) {
        System.out.println("商品->" + item);
    }
}

1.jpg

7.模糊查詢

@Test
public void testFuzzyQuery() {
    NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
    builder.withQuery(QueryBuilders.fuzzyQuery("title", "华为"));

    Page page = commodityRepository.search(builder.build());
    for (Commodity item : page) {
        System.out.println("商品->" + item);
    }
}

8.分页查询

@Test
public void searchByPage() {
    // 构建查询条件
    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    // 添加基本分词查询
    queryBuilder.withQuery(QueryBuilders.matchQuery("category", "手机"));
    // 分页:
    int page = 0;
    int size = 10;
    queryBuilder.withPageable(PageRequest.of(page, size));

    // 搜索,获取结果
    Page items = commodityRepository.search(queryBuilder.build());
    // 总条数
    long total = items.getTotalElements();
    System.out.println("总条数 = " + total);
    // 总页数
    System.out.println("总页数 = " + items.getTotalPages());
    // 当前页
    System.out.println("当前页:" + items.getNumber());
    // 每页大小
    System.out.println("每页大小:" + items.getSize());

    for (Commodity item : items) {
        System.out.println("商品->" + item);
    }
}

SpringBoot整合ElasticSearch_第6张图片

9.排序查询

@Test
public void searchAndSort() {
    // 构建查询条件
    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    // 添加基本分词查询
    queryBuilder.withQuery(QueryBuilders.matchQuery("category", "手机"));

    // 排序
    queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.ASC));

    // 搜索,获取结果
    Page items = commodityRepository.search(queryBuilder.build());
    // 总条数
    long total = items.getTotalElements();
    System.out.println("总条数 = " + total);

    for (Commodity item : items) {
        System.out.println("商品->" + item);
    }
}

10.按照品牌brand进行分组

@Test
public void testAgg() {
    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    // 不查询任何结果
    queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
    // 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
    queryBuilder.addAggregation(
            AggregationBuilders.terms("brands").field("brand"));
    // 2、查询,需要把结果强转为AggregatedPage类型
    AggregatedPage aggPage = (AggregatedPage) commodityRepository.search(queryBuilder.build());
    // 3、解析
    // 3.1、从结果中取出名为brands的那个聚合,
    // 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
    StringTerms agg = (StringTerms) aggPage.getAggregation("brands");
    // 3.2、获取桶
    List buckets = agg.getBuckets();
    // 3.3、遍历
    for (StringTerms.Bucket bucket : buckets) {
        // 3.4、获取桶中的key,即品牌名称
        System.out.println("key->" + bucket.getKeyAsString());
        // 3.5、获取桶中的文档数量
        System.out.println("count->" + bucket.getDocCount());
    }
}

SpringBoot整合ElasticSearch_第7张图片

11.嵌套聚合,求平均值

@Test
public void testSubAgg() {
    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    // 不查询任何结果
    queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
    // 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
    queryBuilder.addAggregation(
            AggregationBuilders.terms("brands").field("brand")
                    .subAggregation(AggregationBuilders.avg("priceAvg").field("price")) // 在品牌聚合桶内进行嵌套聚合,求平均值
    );
    // 2、查询,需要把结果强转为AggregatedPage类型
    AggregatedPage aggPage = (AggregatedPage) commodityRepository.search(queryBuilder.build());
    // 3、解析
    // 3.1、从结果中取出名为brands的那个聚合,
    // 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
    StringTerms agg = (StringTerms) aggPage.getAggregation("brands");
    // 3.2、获取桶
    List 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());
    }

}

1.jpg

你可能感兴趣的:(SpringBoot整合ElasticSearch)