elasticsearch16-聚合API

news2024/11/22 21:03:11

请添加图片描述
个人名片:

博主:酒徒ᝰ.
个人简介沉醉在酒中,借着一股酒劲,去拼搏一个未来。
本篇励志三人行,必有我师焉。

请添加图片描述
本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》,SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式

【SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 点击观看

目录

  • 一、数据聚合
    • 3. RestAPI实现聚合

一、数据聚合

3. RestAPI实现聚合

  1. API语法
    es查询语句
GET /hotel/_search
{
  "size": 0,
  "aggs": {
    "brandAgg": {
      "terms": {
        "field": "brand",
        "size": 20
      }
    }
  }
}

代码示例:

package cn.itcast.hotel;

import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;
import java.util.List;

@SpringBootTest
public class DSLSearch {
    private RestHighLevelClient client;

    @BeforeEach
    void setUp() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("192.168.179.128:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        this.client.close();
    }

    @Test
    void testAggregation() throws IOException {
        SearchRequest request = new SearchRequest("hotel");
        request.source().size(0);
        request.source().aggregation(AggregationBuilders
                .terms("brandAgg")
                .field("brand")
                .size(20));

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        handleResponse(response);
    }

    private void handleResponse(SearchResponse response) {
        Aggregations aggregations = response.getAggregations();
        Terms brandTerms = aggregations.get("brandAgg");
        List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
        for (Terms.Bucket bucket : buckets) {
            String brandName = bucket.getKeyAsString();
            long brandCount = bucket.getDocCount();
            System.out.println(brandName + " " + brandCount);
        }
    }
}

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

  1. 业务需求

需求:搜索页面的品牌、城市等信息不应该是在页面写死,而是通过聚合索引库中的酒店数据得来的:
在这里插入图片描述

分析:

目前,页面的城市列表、星级列表、品牌列表都是写死的,并不会随着搜索结果的变化而变化。但是用户搜索条件改变时,搜索结果会跟着变化。

例如:用户搜索“东方明珠”,那搜索的酒店肯定是在上海东方明珠附近,因此,城市只能是上海,此时城市列表中就不应该显示北京、深圳、杭州这些信息了。

也就是说,搜索结果中包含哪些城市,页面就应该列出哪些城市;搜索结果中包含哪些品牌,页面就应该列出哪些品牌。
如何得知搜索结果中包含哪些品牌?如何得知搜索结果中包含哪些城市?

使用聚合功能,利用Bucket聚合,对搜索结果中的文档基于品牌分组、基于城市分组,就能得知包含哪些品牌、哪些城市了。
因为是对搜索结果聚合,因此聚合是限定范围的聚合,也就是说聚合的限定条件跟搜索文档的条件一致。

查看浏览器可以发现,前端其实已经发出了这样的一个请求:

在这里插入图片描述
在这里插入图片描述
请求参数与搜索文档的参数完全一致
分析:
filter地址,POST请求方式
参数:key, page. size, sortBy, city, starName, brand, minPrice, maxPrice,

返回值类型就是页面要展示的最终结果:
在这里插入图片描述

结果是一个Map结构:
key是字符串,城市、星级、品牌、价格
value是集合,例如多个城市的名称

  1. 业务实现

cn.itcast.hotel.controller包的HotelController中添加一个方法,遵循下面的要求:
请求方式:POST
请求路径:/hotel/filters
请求参数:RequestParams,与搜索文档的参数一致
返回值类型:Map<String, List<String>>

代码:

@PostMapping("/filters")
public Map<String, List<String>> getFilter(@RequestBody RequestParam params) {
    return hotelService.getFilter(params);
}

这里调用了IHotelService中的getFilters方法,尚未实现。

cn.itcast.hotel.service.IHotelService中定义新方法:

Map<String, List<String>> getFilter(RequestParam params);

cn.itcast.hotel.service.impl.HotelService中实现该方法:

@Override
public Map<String, List<String>> getFilter(RequestParam params) {
    try {
        SearchRequest request = new SearchRequest("hotel");
        buildBasicQuery(params, request);
        request.source().size(0);
        buildAggregation(request);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        Map<String, List<String>> result = new HashMap<>();
        Aggregations aggregations = response.getAggregations();
        List<String> brandlist = getAggByName(aggregations, "brandAgg");
        result.put("brand", brandlist);
        List<String> starList = getAggByName(aggregations, "starAgg");
        result.put("starName", starList);
        List<String> cityList = getAggByName(aggregations, "cityAgg");
        result.put("city", cityList);

        return result;
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

private List<String> getAggByName(Aggregations aggregations, String aggName) {
    Terms brandTerm = aggregations.get(aggName);
    List<? extends Terms.Bucket> buckets = brandTerm.getBuckets();
    List<String> list = new ArrayList<>();
    for (Terms.Bucket bucket : buckets) {
        String key = bucket.getKeyAsString();
        list.add(key);
    }
    return list;
}

private void buildAggregation(SearchRequest request) {
    request.source().aggregation(AggregationBuilders
            .terms("brandAgg")
            .field("brand")
            .size(100));
    request.source().aggregation(AggregationBuilders
            .terms("starAgg")
            .field("starName")
            .size(100));
    request.source().aggregation(AggregationBuilders
            .terms("cityAgg")
            .field("city")
            .size(100));
}

结果:

重启项目,刷新浏览器,如果城市中的杭州消失了,则业务实现成功。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1019609.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多媒体隧道

多媒体隧道使压缩的视频数据能够通过硬件视频解码器直接传送到显示器&#xff0c;而无需通过应用程序代码或 Android 框架代码进行处理。 Android 堆栈下方的设备特定代码通过将视频帧呈现时间戳与以下类型的内部时钟之一进行比较来确定将哪些视频帧发送到显示器以及何时发送它…

郑州大学图书馆许少辉《乡村振兴战略下传统村落文化旅游设计》中文文献——2023学生开学季辉少许

郑州大学图书馆许少辉《乡村振兴战略下传统村落文化旅游设计》中文文献——2023学生开学季辉少许

MySQL 几种导数据的方法与遇到的问题

零、说在前面 MySQL导数据通常使用第三方工具和MySQL自身的工具&#xff0c;本文分别就这两类方法分别介绍。 一、第三方工具之 Navicat 1.1、Navicat的“数据传输”工具 打开Navicat&#xff0c;点击“工具”标签&#xff0c;找到“数据传输”&#xff0c;即可看到操作界面。…

SQL Server 日期范围按每月一行拆分

要将 SQL Server 中的日期范围按每月一行拆分&#xff0c;可以使用一个表值函数&#xff08;Table-Valued Function&#xff09;来生成日期范围内的月份&#xff0c;并将其与其他数据连接&#xff0c;以创建包含每月一行的结果集。 以下是一个示例&#xff0c;说明如何实现这一…

怎么用外网访问自己的网站?快解析内网端口映射来实现

想要访问服务器上的网站需要直接或间接访问服务器IP地址&#xff0c;但是如果服务器没有公网IP地址&#xff0c;那么就需要借助外网进行访问。当我们需要远程访问内网的Web服务器时&#xff0c;我们需要使用一些技术来实现此目的。这就需要通过使用类似快解析内网端口映射方式进…

使用HTTP爬虫ip中的常见误区与解决方法

在使用HTTP爬虫进行网页抓取时&#xff0c;涉及到IP地址的处理&#xff0c;可能会存在一些常见的误区。以下是一些常见误区及解决方法&#xff1a; 1.使用个人IP进行大规模爬取&#xff1a;如果你使用个人住宅IP进行大规模爬取&#xff0c;可能会被目标网站视为恶意攻击&#x…

解决Pycharm使用Conda激活环境失败的问题

Q:公司电脑终端使用powershell来激活conda环境时报错? 同时手动打开powershell报"profile.ps1” 无法被加载的错误 A: 1,手动打开powershell&#xff0c;设置管理员打开 2,打开powershell 打开 PowerShell 终端&#xff0c;并输入以下命令&#xff1a;Get-ExecutionPo…

Spring AOP以及统一处理

一.Spring AOP 1.什么是Spring AOP AOP&#xff08;Aspect Oriented Programming&#xff09;&#xff1a;面向切面编程&#xff0c;它是一种思想&#xff0c;它是对某一类事情的集中处理。 2.AOP的作用 想象一个场景&#xff0c;我们在做后台系统时&#xff0c;除了登录…

Java基于SpringBoot的漫画网站,附源码,教程

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 今天为大家带来的是 基于SpringBootVue的漫画之家系统&#xff0c;亲测可用&#xff0c;可以作为课程设计&…

搜索关键词标红组件

搜索关键词标红功能 今年做的一个需求&#xff0c;先看效果图。 先讲一下实现方式&#xff0c;前端输入关键词查询&#xff0c;后端返回html模板&#xff0c;前端通过v-html渲染 查到的数据是分页式&#xff0c;v-html的样式需要使用/deep/声明 下面是组件代码 <template…

现货黄金与黄金一样吗?

在众多的黄金投资方式中&#xff0c;现货黄金可以说是集各家所长于一身的一种&#xff0c;它既承载了实物黄金的特性&#xff0c;能够发挥黄金抗通胀、避风险的重要作用&#xff0c;也拥有纸黄金无需交收的优点&#xff0c;更具有黄金期货可以双向交易、带有资金杠杆的高收益特…

python学习之【包和内置模块】

前言 接上篇文章 python学习之【模块】&#xff0c;这篇文章接着学习python中的包。 python中的包 包是一种用“点式模块名”构造Python模块命名空间的方法。在包中存放着一些功能相近的模块。 包的创建和导入 包的创建 我们可以在pytarm中创建一个package文件&#xff…

【Leetcode热题】打卡day1——10

目录 1、两数之和 - 哈希表 1、两数之和 - 哈希表 1. 两数之和 思路&#xff1a; 建立map&#xff0c;mp[nums[i]]i 存储值所对应的下标 顺序遍历每一个元素&#xff0c;先查找mp中是否存在与nums[i]匹配的值&#xff08;target-nums[i]&#xff09; 如果存在&#xff0c;则返…

如何使用Vcluster实现Kubernetes中的多租户

Kubernetes彻底改变了组织部署和管理容器化应用程序的方式&#xff0c;使跨集群编排和扩展应用程序变得更加容易。然而&#xff0c;在共享的Kubernetes集群上运行多个异构工作负载会带来资源争用、安全风险、缺乏定制和复杂管理等挑战。 以下几种方法可以在Kubernetes中实现隔离…

《golang设计模式》第二部分·结构型模式-05-门面模式Facade)

文章目录 1. 概述1.1 角色1.2 类图 2. 代码示例2.1 设计2.2 代码2.2 类图 1. 概述 门面&#xff08;Facade&#xff09;向客户端提供使用子系统的统一接口&#xff0c;用于简化客户端使用子系统的操作。 1.1 角色 门面角色&#xff08;Facade&#xff09; 客户端可以调用的接…

数字孪生和元宇宙:打造未来的数字边界

数字孪生和元宇宙是近两年来被热议的两个概念&#xff0c;但由于技术的交叉两者也极易被混淆。本文希望带大家深入探讨一下这两者之间的关系&#xff0c;以及它们如何一起构建了数字时代的新格局。 1. 数字孪生的本质 数字孪生是一种虚拟模型&#xff0c;它通过数字手段对现实…

在微信公众号怎么实现投票活动

微信公众号实现投票活动的方法和步骤 一、投票活动的优势 通过投票活动&#xff0c;微信公众号可以实现用户参与、增加互动、了解用户需求等功能&#xff0c;同时也可以提升品牌知名度和用户粘性。以下是一些投票活动的优势&#xff1a; 增加用户参与度&#xff1a;通过投票活…

Seata四种事务模式AT、TCC、SAGA 、 XA详解

文章目录 一、 GlobalTransactional一、AT模式1、原理2 、优缺点3、实现 二、TCC模式1、原理2 、优缺点3、实现 三、SAGA模式1 、原理2 、优缺点3 、实现 四、XA模式1 、原理2 、优缺点3、 实现 五、 四种模式对比 我们知道Seata是一款开源的分布式事务解决方案&#xff0c;致力…

【LeetCode75】第五十八题 组合总和Ⅲ

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目让我们找出长度为k并且总和为n的所有组合&#xff0c;我们能用的元素只有1~9。 那么这种要求排列组合的题&#xff0c;基本是是离不…

2023客服管理者面临的挑战

客服管理者在当今的数字化时代也面临着许多挑战。以下是一些主要的挑战&#xff1a; 同行业竞争加剧&#xff1a;客服行业面临着来自同行业的竞争压力。为了获得竞争优势&#xff0c;企业需要不断提高自身的产品和服务质量&#xff0c;同时还需要不断降低成本、提高效率。然而…