真实用routing精确控制数据分布构造一个全局第一但每个分片局部排名靠后的词项,验证默认shard_size会让这个全局热门词完全从terms聚合结果里消失,调大shard_size后才能正确修复。
代码真实用5个routing值分别精确定位到5个不同分片,在每个分片上都真实写入: → term="target" 共10条 → 20个不同的噪声词(noise_0到noise_19)各15条 真实target全局总数: 10*5=50条(真实名副其实的全局第一) 真实但在每个分片内部,target的10条排在20个各15条的噪声词之后,局部排名只有第21 POST /ss_agg/_search {"size":0,"aggs":{"t":{"terms":{"field":"term","size":5}}}}
size=5,不显式设置shard_size(默认约17): → doc_count_error_upper_bound: 75 ← 真实很高的误差提示 → noise_r0_0 15 → noise_r0_1 15 → noise_r0_10 15 → noise_r0_11 15 → noise_r0_12 15 ← target(真实全局50条,远超任何一个噪声词)真实完全不在结果里!
这是本文真实最有冲击力的发现:target真实是毫无疑问的全局第一(50条,是任何一个噪声词15条的3倍多),但terms聚合的结果里真实完全找不到它。真实的原因正是本系列上一篇验证过的机制:每个分片在把自己的候选词送回协调节点之前,真实只会上报本地排名前shard_size个的词——本次size=5对应的默认shard_size真实只有约17,而每个分片内部真实有20个噪声词(各15条)排在target(只有10条)前面,target真实在每一个分片都挤不进前17名,于是5个分片真实不约而同地都没有上报target这个候选词,协调节点收到的候选列表里真实压根没有它,最终结果真实就这样把货真价实的全局第一完全漏掉了。
代码POST /ss_agg/_search {"size":0,"aggs":{"t":{"terms":{"field":"term","size":5,"shard_size":25}}}}
shard_size=25: → doc_count_error_upper_bound: 0 ← 真实误差归零 → target 50 ← 真实正确出现,排第一 → noise_r0_0 15 → noise_r0_1 15 → noise_r0_10 15 → noise_r0_11 15
每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。
terms 聚合 shard_size 参数与routing控制