2023-08-08  阅读(2)
原文作者:Ressmix 原文地址:https://www.tpvlog.com/article/146

本章,我们来讲下Elasticsearch在进行聚合分析时,所用到的两种遍历算法: 深度优先遍历广度优先遍历 。深度优先遍历和广度优先遍历其实是图的两种基本遍历算法。

一、深度优先

假设我们现在有一些关于电影的数据集,每条doc里面会有一个数组类型的字段,存储着表演该电影的所有演员名字:

    {
      "actors" : [
        "Fred Jones",
        "Mary Jane",
        "Elizabeth Worthing"
      ]
    }

如果我们想要先按演员分组,找到出演影片最多的10个演员;然后,对于每个子组再找出与当前演员合作最多的5个演员,那么可以像下面这样构造请求:

    {
      "aggs" : {
        "actors" : {
          "terms" : {
             "field" : "actors",
             "size" :  10
          },
          "aggs" : {
            "costars" : {
              "terms" : {
                "field" : "actors",
                "size" :  5
              }
            }
          }
        }
      }
    }

但是, 这个看上去简单的查询可以轻而易举地消耗大量内存,我们可以通过在内存中构建一个树来查看这个 terms 聚合。 actors 聚合会构建树的第一层,每个演员都有一个桶。然后,内套在第一层的每个节点之下, costar 聚合会构建第二层,每个联合出演一个桶,这意味着每部影片会生成 nxn 个桶!

202308082147513631.png

上述聚合分析,只是希望得到前10位演员和与他们联合出演者,但是为了得到最终的结果,我们创建了一个有nxn桶的树,然后对其排序,取 top10。如果我们有 2 亿doc,想要得到前 100 位演员以及与他们合作最多的 20 位演员,可以推测,聚合出来的分组数非常大。上述这种遍历方式就是深度优先。

二、广度优先

Elasticsearch 允许我们改变聚合的 集合模式 ,就是为了应对这种状况。 我们之前展示的策略叫做 深度优先 ,它是默认设置, 先构建完整的树,然后修剪无用节点。 深度优先 的方式对于大多数聚合都能正常工作,但对于上述情形就不太适用。

为了应对这些特殊的应用场景,我们应该使用另一种集合策略叫做 广度优先 。这种策略的工作方式有些不同,它先执行第一层聚合, 然后先做修剪,再执行下一层聚合。

在我们的示例中, actors 聚合会首先执行,在这个时候,我们的树只有一层,但我们已经知道了前 10 位的演员,这就没有必要保留其他的演员信息,因为它们无论如何都不会出现在前十位中。

202308082147545062.png

202308082147559803.png

要使用广度优先,只需简单的通过参数 collect_mode 开启:

    {
      "aggs" : {
        "actors" : {
          "terms" : {
             "field" : "actors",
             "size" : 10,
             "collect_mode" : "breadth_first" 
          },
          "aggs" : {
            "costars" : {
              "terms" : {
                "field" : "actors",
                "size" :  5
              }
            }
          }
        }
      }
    }

广度优先 仅仅适用于每个组的聚合数量远小于当前总组数的情况 ,因为广度优先会在内存中缓存裁剪后的每个组的所有数据,如果裁剪后的每个组下的数据量非常大,广度优先就不是一个好的选择,这也是为什么深度优先作为默认策略的原因。

三、总结

本章,我们介绍了Elasticsearch的聚合分析遍历策略,主要有深度优先遍历和广度优先遍历,默认采用深度优先遍历。如果读者对这两种算法感兴趣,可以进一步阅读我的传统算法系列


Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。

它的内容包括:

  • 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
  • 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
  • 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
  • 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
  • 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
  • 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
  • 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
  • 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw

目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:

想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询

同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。

阅读全文