本章,我们来讲下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 个桶!
上述聚合分析,只是希望得到前10位演员和与他们联合出演者,但是为了得到最终的结果,我们创建了一个有nxn桶的树,然后对其排序,取 top10。如果我们有 2 亿doc,想要得到前 100 位演员以及与他们合作最多的 20 位演员,可以推测,聚合出来的分组数非常大。上述这种遍历方式就是深度优先。
二、广度优先
Elasticsearch 允许我们改变聚合的 集合模式 ,就是为了应对这种状况。 我们之前展示的策略叫做 深度优先 ,它是默认设置, 先构建完整的树,然后修剪无用节点。 深度优先 的方式对于大多数聚合都能正常工作,但对于上述情形就不太适用。
为了应对这些特殊的应用场景,我们应该使用另一种集合策略叫做 广度优先 。这种策略的工作方式有些不同,它先执行第一层聚合, 然后先做修剪,再执行下一层聚合。
在我们的示例中, actors
聚合会首先执行,在这个时候,我们的树只有一层,但我们已经知道了前 10 位的演员,这就没有必要保留其他的演员信息,因为它们无论如何都不会出现在前十位中。
要使用广度优先,只需简单的通过参数 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] ,回复【面试题】 即可免费领取。