添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

前文如上:

9.工具使用:Elasticsearch从入门到放弃(1)-Elasticsearch概念篇

10.工具使用:Elasticsearch从入门到放弃(2)-相关性算法

11.工具使用:Elasticsearch从入门到放弃(3)-权重及打分 (qq.com)

1.【Elasticsearch】Elasticsearch从入门到放弃-Elasticsearch概念篇

2.【Elasticsearch】Elasticsearch从入门到放弃-相关性算法

3.【Elasticsearch】Elasticsearch从入门到放弃-权重及打分

4.【Elasticsearch】Elasticsearch从入门到放弃-聚合概述


4. 聚合方式

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

4.1 直接聚合

直接聚合指的是聚合时的DSL没有query子句,是直接对索引内的所有文档进行聚合。前面介绍的示例都属于直接聚合,这里不再进行演示。

4.2 先查询再聚合

image

以下代码演示了在Java中先查询再聚合的逻辑:

image

4.3 前过滤器

有时需要对聚合条件进一步地过滤,但是又不能影响当前的查询条件。例如 用户进行酒店搜索时的搜索条件是天津的酒店,但是聚合时需要将非满房的酒店平均价格进行聚合并展示给用户。此时不能变更用户的查询条件,需要在聚合子句中添加过滤条件 。下面的DSL展示了在聚合时使用过滤条件的用法:

image 执行上述DSL后,ES返回的结果如下:

image 通过上述结果可以知道,满足查询条件的文档个数为2,命中的文档为004和005, 但是在聚合时要求匹配非满房的酒店,只有文档004满足聚合条件,因此酒店的平均值为文档004的price字段值

以下代码演示了在Java中使用前过滤器的逻辑: (注意两个聚合之间前置过滤 满房状态和价格有父子关系)

image

4.4 后过滤器

在有些场景中,需要根据条件进行数据查询,但是聚合的结果集不受影响。例如 在酒店搜索场景中,用户的查询词为“假日”,此时应该展现标题中带有“假日”的酒店。但是在该页面中,如果还希望给用户呈现出全国各个城市的酒店的平均价格,这时可以使用ES提供的后过滤器功能。该过滤器是在查询和聚合之后进行过滤的,因此它的过滤条件对聚合没有影响。 以下的DSL展示了后过滤器的使用:

image

在上面的查询中,使用match匹配title中包含“假日”的酒店,并且查询出这些酒店的平均价格, 最后使用post_filter设置后过滤器的条件,将酒店的城市锁定为“北京” (title包含假日的有四个文档,把找到城市在北京的,只有三个,一个天津的被排除掉了,算平均价格)。执行该DSL后,ES返回的结果如下:

image 以下代码演示了在Java中使用后过滤器的逻辑:

image

5.聚合排序

根据前面的介绍可知,ES对于聚合结果的默认排序规则有时并非是我们期望的。可以使用ES提供的sort子句进行自定义排序,有多种排序方式供用户选择: 可以按照聚合后的文档计数的大小进行排序;可以按照聚合后的某个指标进行排序;还可以按照每个组的名称进行排序 。下面将介绍以上3种排序功能。

5.1 按文档计数排序

在聚合排序时,业务需求可能有按照每个组聚合后的文档数量进行排序的场景。此时可以使用_count来引用每组聚合的文档计数进行排序。以下DSL演示了按照城市的酒店平均价格进行聚合,并按照聚合后的文档计数进行升序排列的请求:

image 执行上述DSL后,ES返回的结果如下:

image 以下代码演示了在Java中使用文档计数进行聚合排序的逻辑:

image

5.2 按聚合指标排序

在聚合排序时,业务需求可能有按照每个组聚合后的指标值进行排序的场景。此时可以使用指标的聚合名称来引用每组聚合的文档计数。以下DSL 演示了按照城市的酒店平均价格进行聚合,并按照聚合后的平均价格进行升序排列的请求

image 执行上述DSL后,ES返回的结果如下:

image 以下代码演示了在Java中按照聚合指标进行聚合排序的逻辑: (城市和平均价格是父子关系)

image

5.3 按分组key排序

在聚合排序时,业务需求可能有按照每个分组的组名称排序的场景。此时可以使用_key来引用分组名称。以下DSL演示了 按照城市的酒店平均价格进行聚合,并按照聚合后的分组名称进行升序排列 的请求:

image 执行上述DSL后,ES返回的结果如下:

image

以下代码演示了在Java中按照分组key进行聚合排序的逻辑:: (城市和平均价格是父子关系) image

6. 聚合分页

ES支持同时返回查询结果和聚合结果,前面介绍聚合查询时,查询结果和聚合结果各自封装在不同的子句中。但 有时我们希望聚合的结果按照每组选出前N个文档的方式进行呈现 ,最常见的一个场景就是电商搜索,如搜索苹果手机6S,搜索结果应该展示苹果手机6S型号中的一款手机即可,而不论该型号手机的颜色有多少种。另外,当聚合结果和查询结果封装在一起时,还需要考虑对结果分页的问题,此时前面介绍的聚合查询就不能解决这些问题了。 ES提供的Top hits聚合和Collapse聚合可以满足上述需求,但是这两种查询的分页方案是不同的。本节将介绍Top hits聚合和Collapse聚合,并分别给出这两种查询的分页方案

6.1 Top hits聚合

顾名思义, Top hits聚合指的是聚合时在每个分组内部按照某个规则选出前N个文档进行展示 。例如,搜索“金都”时,如果希望 按照城市分组,每组按照匹配分数降序展示3条文档 数据,DSL如下:

image 执行上述查询后,ES返回的结果如下:

image 可以看到,在索引中一共有3个文档命中match查询条件,在聚合结果中按照城市分成了两个组“北京”“天津”,在“北京”下面有两个文档命中,并且 按照得分将展示文档进行了降序排列 ,“天津”只有一个文档命中。

image Top hits聚合能满足“聚合的结果按照每组选出N个文档的方式进行呈现”的需求,但是很遗憾,它不能完成自动分页功能。 如果在聚合中使用Top hits聚合并期望对数据进行分页,则要求聚合的结果一定不能太多,因为需要由客户端自行进行分页,此时对分页内存的存储能力是一个挑战。可以一次性获取聚合结果并将其存放在内存中或者Redis中,然后自行实现翻页逻辑,完成翻页。假设数据一次性存储到Redis的list结构中,以下示例代码演示了从Redis分页取数据的逻辑:

image

6.2 Collapse聚合

如前面所述,当 在索引中有大量数据命中时,Top hits聚合存在效率问题,并且需要用户自行排序 。针对上述问题,ES推出了Collapse聚合,即用户可以在collapse子句中指定分组字段,匹配query的结果按照该字段进行分组,并在每个分组中按照得分高低展示组内的文档。当用户在query子句外指定from和size时,将作用在Collapse聚合之后,即此时的分页是作用在分组之后的。以下DSL展示了Collapse聚合的用法:

image

执行上述DSL后,ES返回的结果如下:

image

从结果中可以看到,与Top hits聚合不同,Collapse聚合的结果是封装在hit中的。在索引中一共有3个文档命中match查询条件,在聚合结果中已经按照城市分成了两个组,即“北京”“天津”,在“北京”下面有两个文档命中,其中得分最高的文档为003,“天津”只有一个文档命中。上述结果不仅能按照得分进行排序,并且具备分页功能。

以下代码演示了在Java中使用Collapse聚合的逻辑:

image




【ElasticSearch从入门到放弃系列 十一】Elasticsearch常用查询方式讨论及实践(一)
【ElasticSearch从入门到放弃系列 十一】Elasticsearch常用查询方式讨论及实践
【ElasticSearch从入门到放弃系列 十】Elasticsearch深度分页查询方式讨论
【ElasticSearch从入门到放弃系列 十】Elasticsearch深度分页查询方式讨论
【ElasticSearch从入门到放弃系列 七】Spring Data Elasticsearch的使用
【ElasticSearch从入门到放弃系列 七】Spring Data Elasticsearch的使用
【ElasticSearch从入门到放弃系列 六】Java客户端操作ElasticSearch
【ElasticSearch从入门到放弃系列 六】Java客户端操作ElasticSearch
【ElasticSearch从入门到放弃系列 五】ElasticSearch分布式集群搭建
【ElasticSearch从入门到放弃系列 五】ElasticSearch分布式集群搭建