当前位置: 首页> 科技> IT业 > 巴中网站建设有限公司_汽水音乐怎么推广赚钱_新产品上市推广策划方案_潍坊快速网站排名

巴中网站建设有限公司_汽水音乐怎么推广赚钱_新产品上市推广策划方案_潍坊快速网站排名

时间:2025/7/9 1:30:59来源:https://blog.csdn.net/ren9436/article/details/142281905 浏览次数:0次
巴中网站建设有限公司_汽水音乐怎么推广赚钱_新产品上市推广策划方案_潍坊快速网站排名

Elasticsearch 聚合搜索

  • 环境准备
  • 数据准备
  • 基础聚合
  • 桶聚合(分组聚合)
    • 单维度桶聚合
    • 多维度桶聚合
  • 聚合方式
    • 直接聚合
    • 先查询后聚合
    • 前过滤器
    • 后过滤器
  • 聚合排序
    • 按照文档计数排序
    • 按照聚合指标排序
    • 按照分组Key排序
  • 聚合分页
    • Top hits 聚合
    • Collapse 聚合

当用户使用搜索引擎完成搜索后,在展示结果中需要进行进一步的筛选,而筛选的维度需要根据当前的搜索结果进行汇总,这就用到了聚合技术。

环境准备

  • Elasticsearch 服务(单机或集群)
  • Kibana 服务

如果对ES不了解或没有上述环境,可以看下我之前的博客。

Elasticsearch入门基础和集群部署

Elasticsearch查看集群信息,设置ES密码,Kibana部署

数据准备

PUT /course
{"mappings": {"properties": {"title": {"type": "text"},"teacher_name": {"type": "text"},"price": {"type": "double"},"create_time": {"type": "date","format": ["yyyy-MM-dd HH:mm:ss"]},"tags": {"type": "keyword"},"publish": {"type":"boolean"},"comment_info":{"properties": {"favourable_num":{"type":"integer"},"negative_num":{"type":"integer"}}}}}
}PUT /_bulk
{"index":{"_index":"course","_id":"1"}}
{"title":"Python编程基础","teacher_name":"张三","price":99.99,"create_time":"2023-04-01 10:00:00","tags":["编程","Python"],"publish":true,"comment_info":{"favourable_num":150,"negative_num":3}}
{"index":{"_index":"course","_id":"2"}}
{"title":"Java高级开发","teacher_name":"李四","price":129.5,"create_time":"2023-06-08 15:30:00","tags":["Java","后端开发"],"publish":true,"comment_info":{"favourable_num":200,"negative_num":7}}
{"index":{"_index":"course","_id":"3"}}
{"title":"数据结构与算法","teacher_name":"王五","price":88.88,"create_time":"2023-03-15 14:45:00","tags":["算法","数据结构"],"publish":false,"comment_info":{"favourable_num":50,"negative_num":0}}
{"index":{"_index":"course","_id":"4"}}
{"title":"Web前端开发入门","teacher_name":"赵六","price":79.9,"create_time":"2023-05-20 09:15:00","tags":["HTML","CSS","JavaScript"],"publish":true,"comment_info":{"favourable_num":88,"negative_num":2}}
{"index":{"_index":"course","_id":"5"}}
{"title":"机器学习实战","teacher_name":"孙七","price":159,"create_time":"2023-02-25 11:00:00","tags":["机器学习","人工智能"],"publish":true,"comment_info":{"favourable_num":120,"negative_num":5}}
{"index":{"_index":"course","_id":"6"}}
{"title":"数据库原理与设计","teacher_name":"周八","price":66.6,"create_time":"2023-01-10 13:30:00","tags":["数据库","SQL"],"publish":false,"comment_info":{"favourable_num":30,"negative_num":1}}
{"index":{"_index":"course","_id":"7"}}
{"title":"Android应用开发","teacher_name":"吴九","price":119.88,"create_time":"2023-04-20 17:45:00","tags":["Android","移动开发"],"publish":true,"comment_info":{"favourable_num":105,"negative_num":4}}
{"index":{"_index":"course","_id":"8"}}
{"title":"深度学习探索","teacher_name":"郑十","price":299,"create_time":"2023-05-05 16:00:00","tags":["深度学习","神经网络"],"publish":true,"comment_info":{"favourable_num":180,"negative_num":6}}
{"index":{"_index":"course","_id":"9"}}
{"title":"UI/UX设计精髓","teacher_name":"钱十一","price":55.55,"create_time":"2023-03-20 12:15:00","tags":["UI设计","用户体验"],"publish":true,"comment_info":{"favourable_num":75,"negative_num":2}}
{"index":{"_index":"course","_id":"10"}}
{"title":"云计算技术基础","teacher_name":"孙十二","create_time":"2023-07-01 18:30:00","tags":["云计算","AWS"],"publish":false,"comment_info":{"favourable_num":45,"negative_num":0}}

基础聚合

# 聚合指令
"aggs":{// 指定聚合内容"value_count_price":{// 指定方法"value_count": {//指定聚合字段"field": "price"}}}

基础聚合方法

  • 平均值 avg
  • 最大 max
  • 最小 min
  • 计数 value_count
  • 求和 sum
  • 统计聚合 stats

注意: 上述基础聚合,非空值不会参与计算
例如:十个文档数据,其中有一个文档中字段为空,对其求平均值,结果应该是: 字段不为空的9个文档的平均值。
对于空值:可以使用missing 字段,指定 将空值替换为某个值 来参与计算

在这里插入图片描述

桶聚合(分组聚合)

在ES中,MYSQL 中的 Group by 分组 被称为 桶聚合

单维度桶聚合

单维度桶聚合 就是 按照一个维度对文档 进行分组聚合
在桶聚合时匹配方式

  • terms

terms聚合是按照字段的实际完整值进行匹配和分组的,它使用的维度字段必须是keyword、bool、keyword数组等适合精确匹配的数据类型,因此不能对text字段直接使用terms聚合,如果对text字段有terms聚合的需求,则需要在创建索引时为该字段增加多字段功能。

  • ranges

ranges聚合也是经常使用的一种聚合。它匹配的是数值字段,表示按照数值范围进行分组。用户可以在ranges中添加分组,每个分组用from和to表示分组的起止数值。注意该分组包含起始数值,不包含终止数值。

  • filter

filter聚合使用和搜索时使用方法一样,用来过滤出一批数据,一般用于 不影响查询条件的前过滤器

GET /course/_search
{// 桶聚合默认 计算每个桶对应的文档数"size": 0,"aggs":{"agg_terms_tags":{// 默认只返回十个桶,即size为10 "terms": {"field": "tags"}},"agg_terms_publish":{"terms": {"field": "publish","size": 10}},"agg_range_price":{"range": {"field": "price","ranges": [//不指定from (-∞,80){"to": 80},// 左闭右开 [80,100){"from": 80,"to": 100},//不指定to [100,+∞){"from": 100}]}},"agg_filter_price": {"filter": {"match": {"publish": "true"}}}}
}

在这里插入图片描述
注意: 这里多了一个 key_as_string 字段。

如果桶字段类型不是keyword类型,ES在聚合时会将桶字段转换为Lucene存储的实际值进行识别。true在Lucene中存储为1,false在Lucene中存储为0。而key_as_string 则用来表示原始值的字符串形式。

在这里插入图片描述

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

在默认情况下,进行桶聚合时如果不指定指标,则ES默认聚合的是文档计数,该值以doc_count为key存储在每一个bucket子句中。

返回的doc_count 是近似值,并不是一个准确数,
因此在聚合外围,ES给出了两个参考值doc_count_error_upper_boundsum_other_doc_count

doc_count error_upper表示被遗漏的文档数量可能存在的最大值。
sum other doc count表示除了返回给用户的文档外剩下的文档总数。

多维度桶聚合

通常,在一些复杂业务中,单维度的桶聚合无法满足需求。
往往需要引入多维度的嵌套桶聚合。

例如:分别获取发布和未发布状态 价格 在 (-∞,80),[80,100),[100,+∞) 的 价格平均值

分析上述 需求,按照关系数据库的思路,其实就是 按照 发布状态 和 这三个价格区间进行分组 求每个组的平均价格
对应ES 中的桶聚合,可以转化为 求两个维度的桶聚合,

  1. 按照 发布状态 进行分组聚合
  2. 在聚合的结果中,按照价格区间进行分组聚合
  3. 在最新的聚合桶中 计算平均价格

转化为DSL如下:

GET /course/_search
{"size": 0,"aggs": {// 第一层分组桶:按照发布状态分组"publish_group": {"terms": {"field": "publish"},"aggs": {// 第二层分组:按照价格区间分组"price_range_group": {"range": {"field": "price","ranges": [{"to": 80},{"from": 80,"to": 100},{"from": 100}]},"aggs": {// 聚合计算平均值,也可以算一层"ans_avg": {"avg": {"field": "price"}}}}}}}
}

在这里插入图片描述
第一个桶 publish 为 true 时,内部嵌套了 价格区间的桶,每个价格区间内又有计算的 平均值 ans_avg

在这里插入图片描述
第二个桶 publish 为 false 时,内部嵌套了 价格区间的桶,每个价格区间内又有计算的 平均值 ans_avg

聚合方式

ES支持灵活的聚合方式,它不仅支持聚合和查询相结合,而且还可以使聚合的过滤条件不影响搜索条件,并且还支持在聚合后的结果中进行过滤选。

直接聚合

直接聚合指的是聚合时的DSL没有query子句,是直接对索引内的所有文档进行聚合。
前面的案例都是使用直接聚合方式

先查询后聚合

与直接聚合相对应,这种查询方式需要增加query子句,query子句和普通的query查询没有区别,参加聚合的文档必须匹配query查询。

对应的 就是 SQL 语言中的 Where语句

例如:查询发布状态的 课程 在 价格区间 (-∞,80),[80,100),[100,+∞) 中的平均价格

GET /course/_search
{"query": {"match": {"publish": "true"}},"size": 0,"aggs": {"price_range_group": {"range": {"field": "price","ranges": [{"to": 80},{"from": 80,"to": 100},{"from": 100}]},"aggs": {"ans_avg": {"avg": {"field": "price"}}}}}
}

在这里插入图片描述

前过滤器

有时需要对聚合条件进一步地过滤,但是又不能影响当前的查询条件。

例如:查询全部课程,并计算已经上架的课程的平均价格

因为 未上架的课程 也不能买,所以其平均价格没有意义

这时 需要用到 filter 关键字,在聚合前进行过滤,但不影响query数据

SQL 中没有 前过滤器 关键字,但可以通过 case when end 实现相似的效果

对应DSL语句为:

GET /course/_search
{"size": 0,"aggs": {"my_aggs": {"filter": {"term": {"publish": "true"}},"aggs": {"ans_avg": {"avg": {"field": "price"}}}}}
}

在这里插入图片描述

后过滤器

在有些场景中,需要根据条件进行数据查询,但是聚合结果不受影响。

例如:求全部数据的平均值,但只需输出下架的课程

这时 需要使用 post_filter 关键字 进行 聚合后的 后置过滤,但不影响aggs聚合

可以类比 SQL语句中的 having 关键字,分组后进行数据筛选

GET /course/_search
{"size": 10,"post_filter": {"term": {"publish": "false"}}, "aggs": {"ans_avg": {"avg": {"field": "price"}}}
}

在这里插入图片描述
注意:

ans_avg 还是计算的 query 查询出来的数据的平均值
而 post_filter 作用于 聚合计算后,再过滤数据,所以 只输出了三个 publish 为false 的数据

聚合排序

按照文档计数排序

可以使用_count 来进行文档计数排序

GET /course/_search
{"size": 0,"aggs": {"agg_terms_publish1": {"terms": {"field": "publish","order": {"_count": "asc"}}}}
}

按照聚合指标排序

可以使用具体的聚合指标名称 来进行排序

GET /course/_search
{"size": 0,"aggs": {"agg_terms_publish1": {"terms": {"field": "publish","order": {"avg_aggs": "desc"}},"aggs": {"avg_aggs": {"avg": {"field": "price"}}}}}
}

按照分组Key排序

在聚合排序时,业务需求可能有按照每个分组的组名称排序的场景。此时可以使用 key来引用分组名称。
按照分组Key的自然顺序升序排列

GET /course/_search
{"size": 0,"aggs": {"agg_terms_publish1": {"terms": {"field": "publish","order": {"_key": "asc"}}}}
}

聚合分页

ES支持同时返回查询结果和聚合结果,前面介绍聚合查询时,查询结果和聚合结果各自封装在不同的子句中。

但有时我们希望聚合的结果按照每组选出前N个文档的方式进行呈现,最常见的一个场景就是电商搜索,如搜索苹果手机6S,搜索结果应该展示苹果手机6S型号中的一款手机即可,而不论该型号手机的颜色有多少种。

另外,当聚合结果和查询结果封装在一起时,还需要考虑对结果分页的问题,此时前面介绍的聚合查询就不能解决这些问题了。

ES提供的Top hits聚合和Collapse聚合可以满足上述需求,但是这两种查询的分页方案是不同的。

Top hits 聚合

Top hits聚合指的是聚合时在每个分组内部,按照某个规则选出前N个文档进行展示。
例如: 搜索 “开发”时,按照上下架分组,每组按照价格升序,展示最便宜的数据

GET /course/_search
{"query": {"match": {"title": "开发"}},"size": 0,"aggs": {"group_publish": {"terms": {"field": "publish"},"aggs": {"top_aggs": {"top_hits": {"size": 1,"sort": {"price": {"order": "asc"}}}}}}}
}

在这里插入图片描述

Collapse 聚合

当在索引中有大量数据命中时,Top hits聚合存在效率问题,并且需要用户自行排序。

针对上述问题,ES推出了Collapse聚合,即用户可以在collapse子句中指定分组字段,匹配query的结果按照该字段进行分组,并在每个分组中按照得分高低展示组内的文档。

当用户在query子句外指定from和size时,将作用在Collapse聚合之后,即此时的分页是作用在分组之后的。

GET /course/_search
{"query": {"match": {"title": "开发"}},"from": 0,"size": 2,"collapse": {"field": "price"}
}
关键字:巴中网站建设有限公司_汽水音乐怎么推广赚钱_新产品上市推广策划方案_潍坊快速网站排名

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: