分布式搜索引擎03

1.数据聚合

聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如:

  • 什么品牌的手机最受欢迎?

  • 这些手机的平均价格、最高价格、最低价格?

  • 这些手机每月的销售情况如何?

实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实现近实时搜索效果。

1.1.聚合的种类

聚合常见的有三类:

  • 桶(Bucket)聚合:用来对文档做分组

    • TermAggregation:按照文档字段值分组,例如按照品牌值分组、按照国家分组

    • Date Histogram:按照日期阶梯分组,例如一周为一组,或者一月为一组

  • 度量(Metric)聚合:用以计算一些值,比如:最大值、最小值、平均值等

    • Avg:求平均值

    • Max:求最大值

    • Min:求最小值

    • Stats:同时求max、min、avg、sum等

  • 管道(pipeline)聚合:其它聚合的结果为基础做聚合

注意:参加聚合的字段必须是keyword、日期、数值、布尔类型

 1.2.DSL实现聚合

现在,我们要统计所有数据中的酒店品牌有几种,其实就是按照品牌对数据分组。此时可以根据酒店品牌的名称做聚合,也就是Bucket聚合。

1.2.1.Bucket聚合语法

语法如下:

GET /hotel/_search
{
  "size": 0,  // 设置size为0,结果中不包含文档,只包含聚合结果
  "aggs": { // 定义聚合
    "brandAgg": { //给聚合起个名字
      "terms": { // 聚合的类型,按照品牌值聚合,所以选择term
        "field": "brand", // 参与聚合的字段
        "size": 20 // 希望获取的聚合结果数量
      }
    }
  }
}

结果如图:

1.2.2.聚合结果排序

默认情况下,Bucket聚合会统计Bucket内的文档数量,记为count,并且按照count降序排序。

我们可以指定order属性,自定义聚合的排序方式:

GET /hotel/_search
{
  "size": 0, 
  "aggs": {
    "brandAgg": {
      "terms": {
        "field": "brand",
        "order": {
          "_count": "asc" // 按照_count升序排列
        },
        "size": 20
      }
    }
  }
}

1.2.3.限定聚合范围

默认情况下,Bucket聚合是对索引库的所有文档做聚合,但真实场景下,用户会输入搜索条件,因此聚合必须是对搜索结果聚合。那么聚合必须添加限定条件。

我们可以限定要聚合的文档范围,只要添加query条件即可:

GET /hotel/_search
{
  "query": {
    "range": {
      "price": {
        "lte": 200 // 只对200元以下的文档聚合
      }
    }
  }, 
  "size": 0, 
  "aggs": {
    "brandAgg": {
      "terms": {
        "field": "brand",
        "size": 20
      }
    }
  }
}

这次,聚合得到的品牌明显变少了:

1.2.4.Metric聚合语法

上节课,我们对酒店按照品牌分组,形成了一个个桶。现在我们需要对桶内的酒店做运算,获取每个品牌的用户评分的min、max、avg等值。

这就要用到Metric聚合了,例如stat聚合:就可以获取min、max、avg等结果。

GET /hotel/_search
{
  "size": 0, 
  "aggs": {
    "brandAgg": { 
      "terms": { 
        "field": "brand", 
        "size": 20
      },
      "aggs": { // 是brands聚合的子聚合,也就是分组后对每组分别计算
        "score_stats": { // 聚合名称
          "stats": { // 聚合类型,这里stats可以计算min、max、avg等
            "field": "score" // 聚合字段,这里是score
          }
        }
      }
    }
  }
}

这次的score_stats聚合是在brandAgg的聚合内部嵌套的子聚合。因为我们需要在每个桶分别计算。

另外,我们还可以给聚合结果做个排序,例如按照每个桶的酒店平均分做排序:

1.2.5.小结

aggs代表聚合,与query同级,此时query的作用是?

  • 限定聚合的的文档范围

聚合必须的三要素:

  • 聚合名称

  • 聚合类型

  • 聚合字段

聚合可配置属性有:

  • size:指定聚合结果数量

  • order:指定聚合结果排序方式

  • field:指定聚合字段

1.3.RestAPI实现聚合

1.3.1.API语法

聚合条件与query条件同级别,因此需要使用request.source()来指定聚合条件。

聚合条件的语法:

聚合的结果也与查询结果不同,API也比较特殊。不过同样是JSON逐层解析:

1.3.2.业务需求

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

​​​​​​​使用聚合功能,利用Bucket聚合,对搜索结果中的文档基于品牌分组、基于城市分组,就能得知包含哪些品牌、哪些城市了。

因为是对搜索结果聚合,因此聚合是限定范围的聚合,也就是说聚合的限定条件跟搜索文档的条件一致。

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

请求参数与搜索文档的参数完全一致

返回值类型就是页面要展示的最终结果:

结果是一个Map结构:

  • key是字符串,城市、星级、品牌、价格

  • value是集合,例如多个城市的名称

1.3.3.业务实现

  • 请求方式:POST

  • 请求路径:/hotel/filters

  • 请求参数:RequestParams,与搜索文档的参数一致

  • 返回值类型:Map<String, List<String>>

代码:

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

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

IHotelService中定义新方法:

Map<String, List<String>> filters(RequestParams params);

impl.HotelService中实现该方法:

@Override
public Map<String, List<String>> filters(RequestParams params) {try {// 1.准备RequestSearchRequest request = new SearchRequest("hotel");// 2.准备DSL// 2.1.querybuildBasicQuery(params, request);// 2.2.设置sizerequest.source().size(0);// 2.3.聚合buildAggregation(request);// 3.发出请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.解析结果Map<String, List<String>> result = new HashMap<>();Aggregations aggregations = response.getAggregations();// 4.1.根据品牌名称,获取品牌结果List<String> brandList = getAggByName(aggregations, "brandAgg");result.put("品牌", brandList);// 4.2.根据品牌名称,获取品牌结果List<String> cityList = getAggByName(aggregations, "cityAgg");result.put("城市", cityList);// 4.3.根据品牌名称,获取品牌结果List<String> starList = getAggByName(aggregations, "starAgg");result.put("星级", starList);return result;} catch (IOException e) {throw new RuntimeException(e);}
}private void buildAggregation(SearchRequest request) {request.source().aggregation(AggregationBuilders.terms("brandAgg").field("brand").size(100));request.source().aggregation(AggregationBuilders.terms("cityAgg").field("city").size(100));request.source().aggregation(AggregationBuilders.terms("starAgg").field("starName").size(100));
}private List<String> getAggByName(Aggregations aggregations, String aggName) {// 4.1.根据聚合名称获取聚合结果Terms brandTerms = aggregations.get(aggName);// 4.2.获取bucketsList<? extends Terms.Bucket> buckets = brandTerms.getBuckets();// 4.3.遍历List<String> brandList = new ArrayList<>();for (Terms.Bucket bucket : buckets) {// 4.4.获取keyString key = bucket.getKeyAsString();brandList.add(key);}return brandList;
}

2.自动补全

当用户在搜索框输入字符时,我们应该提示出与该字符有关的搜索项,如图:

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

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

相关文章

Zookeeper单机模式搭建

1、下载 ​wget https://dlcdn.apache.org/zookeeper/zookeeper-3.6.3/apache-zookeeper-3.6.3-bin.tar.gz 2、解压 tar -zxvf apache-zookeeper-3.6.3-bin.tar.gz 3、进入 apache-zookeeper-3.6.3-bin目录下&#xff0c;创建data cd apache-zookeeper-3.6.3-bin mkdir da…

Matlab 用矩阵画图

文章目录 Part.I IntroductionChap.I 预备知识Chap.II 概要Chap.III 杂记 Part.II 用矩阵画图Chap.I 摸索过程Chap.II 绘制专业图Chap.III 矩阵转tiff Part.I Introduction 本文汇总了 Matlab 用矩阵画图的几种方式。 Chap.I 预备知识 关于 *.mat 文件 *.mat文件是 matlab 的…

如何加快网络攻击发现速度

网络攻击可能会摧毁受害者。例如&#xff0c;米高梅度假村 (MGM Resorts) 预计将因 9 月份的网络攻击而遭受 1 亿美元的损失。 鲜为人知的是&#xff0c;在许多情况下&#xff0c;借助网络攻击发现可以预防网络攻击或将其消灭在萌芽状态。 威胁行为者变得越来越复杂&#xff…

网络管理相关

管理功能分为管理站manager和代理agent两部分。 网络管理&#xff1a; 网络管理系统中&#xff0c;每一个网络节点都包含有一组与管理有关的软件&#xff0c;叫做网络管理实体NME。 管理站的另外一组软件叫做网络管理应用NMA&#xff0c;提供用户接口&#xff0c;根据用户命令显…

2021年第十届数学建模国际赛小美赛B题疾病传播的风险解题全过程文档及程序

2021年第十届数学建模国际赛小美赛 B题 疾病传播的风险 原题再现&#xff1a; 空气传播疾病可以通过咳嗽或打喷嚏、喷洒液体或灰尘传播。另一方面&#xff0c;一些常见的传染病只能通过飞沫传播。请建立一个模型&#xff0c;以评估密闭空间内空气传播和液滴传播疾病的可能性。…

常用API

API(全称 Application Programming Interface&#xff1a;应用程序编程接口) 就是别人写好的一些程序&#xff0c;给我们直接拿去调用即可解决问题的。 包 什么是包&#xff1f; 包是用来分门别类的管理各种不同程序的&#xff0c;类似于文件夹&#xff0c;建包有利于程序的管…

【AIGC】prompt工程从入门到精通--图片生成专题

本文为系列教程【AIGC】prompt工程从入门到精通的子教程。 一、介绍 与文本提示相比&#xff0c;找到最佳的提示词来生成完美的图片并没有那么成熟。这可能是因为创建对象自身的挑战&#xff0c;这些对象基本上是主观的并且往往缺乏良好的准确性度量方法。 本指南涵盖了基本…

.NET 8 中 Android 资源生成的改进和变化

作者&#xff1a;Dean Ellis 排版&#xff1a;Alan Wang 随着 .NET 8 的发布&#xff0c;我们引入了一个新系统&#xff0c;用于生成访问 Android 资源的 C# 代码。 在 Xamarin.Android、.NET 6 和 .NET 7 中生成 Resource.designer.cs 文件的系统已经被弃用。 新系统生成一个名…

No Chromedriver found that can automate Chrome ‘x.x.xxxx‘的解决办法

一、前置说明 在使用Appium对Android设备自动化测试时&#xff0c;切换WebView时抛出异常&#xff1a; selenium.common.exceptions.WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: No Chromedriver foun…

交叉验证以及scikit-learn实现

交叉验证 交叉验证既可以解决数据集的数据量不够大问题&#xff0c;也可以解决参数调优的问题。 主要有三种方式&#xff1a; 简单交叉验证&#xff08;HoldOut检验&#xff09;、k折交叉验证&#xff08;k-fold交叉验证&#xff09;、自助法。 本文仅针对k折交叉验证做详细解…

基于ssm vue个人需求和地域特色的外卖推荐系统源码和论文

首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数据库设计。本项…

利用管道、信号量、信号、共享内存和消息队列进行多进程通信

一.管道&#xff08;分为命名管道和匿名管道&#xff09; 管道的特点&#xff1a; ①无论是命名管道还是匿名管道&#xff0c;写入管道的数据都存放在内存之中。 ②管道是一种半双工的通信方式&#xff08;半双工是指终端A能发信号给终端B&#xff0c;终端B也能发信号给终端…

软件开发安全指南

2.1.应用系统架构安全设计要求 2.2.应用系统软件功能安全设计要求 2.3.应用系统存储安全设计要求 2.4.应用系统通讯安全设计要求 2.5.应用系统数据库安全设计要求 2.6.应用系统数据安全设计要求 软件开发全资料获取&#xff1a;点我获取

Linux 网络协议

1 网络基础 1.1 网络概念 网络是一组计算机或者网络设备通过有形的线缆或者无形的媒介如无线&#xff0c;连接起来&#xff0c;按照一定的规则&#xff0c;进行通讯的集合( 缺一不可 )。 5G的来临以及IPv6的不断普及&#xff0c;能够进行联网的设备将会是越来越多&#xff08…

vue 商品列表案例

my-tag 标签组件的封装 1. 创建组件 - 初始化 2. 实现功能 (1) 双击显示&#xff0c;并且自动聚焦 v-if v-else dbclick 操作 isEdit 自动聚焦&#xff1a; 1. $nextTick > $refs 获取到dom&#xff0c;进行focus获取焦点 2. 封装v-focus指令 (2) 失去焦点&#xff0c;隐藏…

用Rust刷LeetCode之66 加一

66. 加一[1] 难度: 简单 func plusOne(digits []int) []int { length : len(digits) // 从最低位开始遍历&#xff0c;逐位加一 for i : length - 1; i > 0; i-- { if digits[i] < 9 { digits[i] return digits } d…

【Mac】brew提示arch -arm64 brew以及uname返回x86_64的问题

背景 使用MacBook 14 M1 Pro两年了&#xff0c;自从使用了第三方Shell工具WindTerm后&#xff0c;使用brew时会提示我使用arch -arm64 brew安装&#xff0c;一开始没太在意&#xff0c;直到今天朋友问我uname -a返回的是什么架构&#xff0c;我才惊讶的发现竟然返回的是x86_64…

优化系统性能:深入性能测试的重要性与最佳实践

目录 引言 1. 为什么性能测试重要&#xff1f; 1.1 用户体验 1.2 系统稳定性 1.3 成本节约 1.4 品牌声誉 2. 性能测试的关键步骤 2.1 制定性能测试计划 2.2 确定性能测试类型 2.3 设计性能测试用例 2.4 配置性能测试环境 2.5 执行性能测试 2.6 分析和优化 2.7 回…

QT----Visual Studio打开.ui文件报错无法打开

问题 在我安装完qt后将它嵌入vs&#xff0c;后新建的文件无法打开ui文件 解决方法 右击ui文件打开方式,添加,程序找到你qt的安装目录里的designer.exe。点击确定再次双击就能够打开。

VMware提示:此虚拟机似乎正在使用中,取得该虚拟机的所有权失败错误的解决方案

当你遇到这个的时候是不是很疑惑&#xff0c;现在给你解决方案 step1: 先找到配置文件目录 D:\centOs7_mini\ 这里写成你的这个 step2: 在这个地方查找最后面是 .vmx.lck文件夹,然后进行修改、删除、移动都可以 step3: 去虚拟机那边重新启动就行