下面的json是https://www.elastic.co/blog/top-hits-aggregation/
{
"query":{
"match":{
"body":"web"
}
},
"size":1,
"aggs":{
"top-programming-languages":{
"terms":{
"field":"tags",
"include":"java|javascript|python|php|python|ruby|perl|c#",
"size":10,
"order":{
"max_score":"desc"
}
},
"aggs":{
"top-questions":{
"top_hits":{
"size":1
}
},
"max_score":{
"max":{
"lang":"expression",
"script":"doc.score"
}
}
}
}
}
}
我只是不明白这里的逻辑。
首先执行以下查询,只返回一个结果。
"query":{
"match":{
"body":"web"
}
},
"size":1,
接下来 top-programming-languages
聚合只在这一条记录上运行?
而在 top-programming-languages -> term -> order
, max_score
是必需的,但直到 top-programming-languages -> aggs -> max_score
聚合完成。那怎么可能呢 top-programming-languages -> term
可以执行吗?
似乎es使用了反直觉的执行顺序,但是我在它的文档中找不到解释。
有人能帮我吗?提前谢谢!
1条答案
按热度按时间wj8zmpe11#
执行查询并匹配n个文档。
在这n个文档中,只返回一个,即得分最高的文档(因为它是一个
match
查询,所以排名第一)。然后,在查询和
tags
从所有这些文件中汇总。在索引的每个片段上,标签都是按这样的方式排列的,即那些包含具有最高优先级的文档的标签
doc.score
先来。对于每个bucket,最上面的文档都出现在top-questions
子聚合。最后,将每个shard的前10个bucket返回给协调节点。但是,由于只包含7个标记(python列出了两次),因此每个shard可能只有7个bucket。协调节点然后将它们组合在一起,并根据需要对所有碎片中的所有标记桶进行重新排序
max_score
只拿前10桶。假设您的索引有2个碎片和以下文档(为了更简单,我将采用
size: 5
而不是10,因为你的include
条款与尺寸10冲突):碎片1:
碎片2:
在每个碎片上,标签桶看起来是这样的(由
max(doc.score)
):碎片1:
碎片2:
只有前5个将返回到协调节点,协调节点将重新组合所有bucket并再次对它们进行排序,并且只获取前5个bucket,这将生成这些最终bucket:
所以,正如你所看到的,执行顺序是相互交织的。bucketing和排序在每个shard上发生一次,然后在协调节点上再次发生。但这不像是先计算桶的顺序,然后再计算桶,等等。。。这几乎是同时发生的,bucketing/ordering也首先以分布式的方式执行,最后一切都是集中的,类似于map/reduce所做的,在es中称为scatter/gather。