Elasticsearch terms聚合不准确的问题

默认情况

默认情况下,terms聚合只返回文档数Top10的term统计。如果想返回更多的词项分桶,可以设置"size"参数。

Size参数

{"aggs" : {"products" : {"terms" : {"field" : "product","size" : 5}}}
}

1.如果不指定,size默认10.
2.size参数决定了terms聚合最多有多少个term bucket返回给客户端(由协调节点返回)。
3.默认情况下协调节点向目标分片请求它们的Top size个term bucket. 之后每个分片的term bucket都在协调节点上reduce,最终返回给客户端。

统计误差 & 遗漏

这种协调节点先请求各自分片的top size词项统计列表,之后再在协调节点上合并最终top size的方式存在误差,以下面对product字段聚合为例:

{"aggs" : {"products" : {"terms" : {"field" : "product","size" : 5}}}
}

假设目标索引共三个分片,并且各分片词项分布如下:

由于size=5,那么协调节点会要求各分片返回各自的top 5词项统计,也就是上图的红框部分。之后在协调节点上,对各分片的top5统计(红框内)进行reduce合并,合并后的结果为:

这个返回结果有以下问题需要注意:

  1. 由于 ProductA(100) 这个结果是由三个分片各自的ProductA统计结果合并得到的(25+30+45),因此排名第一的 ProductA(100) 是准确的,没什么问题。
  2. ProductC(50) 的统计结果由 ShardA 和 ShardC 的结果合并(6+44),但是这个结果却是有问题的,因为 ShardB 上还有 ProductC(4) 没有被统计到,原因是 ProductC(4) 并没有排进 ShardB 的Top5,导致统计遗漏。
  3. ProductZ(52) 也是由 ShardB 和 ShardC 的结果合并而来(16+36),但是这个结果却又是准确的,因为 ShardA 确实没有ProductC这个词项,不存在遗漏统计的问题。
  4. 协调节点在进行最终结果合并的时候,并没有办法区分情况2和情况3,因此不能保证最终terms聚合结果的词项统计是准确的。
  5. 对于 ProductH 这个词项,它在三个分片上都存在(2+14+28),ProductH(44)理应排进最终结果的第4位,但是最终结果中并没有 ProductH(44),因此 ProductH 被遗漏,原因是它没有排进各自分片的Top5.

Shard Size参数

为了解决以上问题,最容易想到的就是加大Size参数,size越大,最终结果越准。

但是过大的size会增加协调节点合并的压力,并且对于业务上来说,我明明只想要查询TOP5,可我却必须返回TOP100,这会导致不必要的网络传输和数据处理。

更合理的方案是显示设置"shard_size"参数,它可以控制协调节点要求各分片返回TOP shard_size。之后协调节点再从各"TOP shard_size"结果中合并出 “TOP size”。

"shard_size"不能设置得比"size"小,这没有意义,如果shard_size < size,ES后台会强制改写成shard_size = size。

两个反应误差的参数

{..."aggregations" : {"products" : {"doc_count_error_upper_bound" : 46,"buckets" : [{"key" : "Product A","doc_count" : 100},{"key" : "Product Z","doc_count" : 52}...]}}
}

总的doc_count_error_upper_bound

可以看到返回的结果中有一个参数:“doc_count_error_upper_bound”。

这个参数表示了 遗漏词项(不在最终结果中的词项)的最大可能文档数。它的值是各分片返回的最后一个词项的文档数的和,就是红框中的第五行(2+15+29)=46。

在上面的例子中,这意味着,在最坏情况下,一个被遗漏的词项,至多可能出现在最终TOP5 的第4位,比如ProductH(44),实际应该是在第5。

各词项的doc_count_error_upper_bound

通过设置"show_term_doc_count_error":true来开启:

GET /_search
{"aggs" : {"products" : {"terms" : {"field" : "product","size" : 5,"show_term_doc_count_error": true}}}
}
{..."aggregations" : {"products" : {"doc_count_error_upper_bound" : 46,"buckets" : [{"key" : "Product A","doc_count" : 100,"doc_count_error_upper_bound" : 0},{"key" : "Product Z","doc_count" : 52,"doc_count_error_upper_bound" : 2}...]}}
}

各词项的"doc_count_error_upper_bound"表示当前词项的最大误差

它的值计算方式为:

  1. 从各分片返回结果中,筛选出没有出现当前词项的结果
  2. 计算上述结果中最后一个词项的和。

比如ProductZ,只有ShardA的返回结果中没有,ShardA返回的最后一个词项的和是ProductE(2)。表示ProductZ的文档统计数最大可能有2的误差。

同理,有ProductC,只有ShardB没有,ShardB返回的最后一个词项的和是ProductG(15),表示ProductC的文档数最大可能有15的误差。

计算doc_count_error_upper_bound的条件

只有在聚合结果按照 文档数降序(默认就是这样) 排序的时候,才会统计这些误差。
以下情况返回"doc_count_error_upper_bound":“-1” :

  1. 按照词项值本身排序(无论升序还是降序),因为这种情况没有误差,因为此时如果分片的TOP N中没有该词项,那一定是这个词项就在该分片中不存在。
  2. 按照当前文档数升序,或者按照子聚合结果排序,也无法统计误差。

关于排序

默认按照文档数降序。

按文档数排序

GET /_search
{"aggs" : {"genres" : {"terms" : {"field" : "genre","order" : { "_count" : "asc" }}}}
}

不鼓励按照子聚合排序或者文档数升序,否则误差没有上限,除非:

  1. 目标索引只有当个分片。
  2. 正在聚合的字段被用作文档索引路由的key。
  3. 按自聚合排序且子聚合为max或者min。

按词项本身排序

GET /_search
{"aggs" : {"genres" : {"terms" : {"field" : "genre","order" : { "_key/_term" : "asc" }}}}
}

按照子聚合排序

GET /_search
{"aggs" : {"genres" : {"terms" : {"field" : "genre","order" : { "max_play_count" : "desc" }},"aggs" : {"max_play_count" : { "max" : { "field" : "play_count" } }}}}
}// 如果内部聚合是多值的:
GET /_search
{"aggs" : {"genres" : {"terms" : {"field" : "genre","order" : { "playback_stats.max" : "desc" }},"aggs" : {"playback_stats" : { "stats" : { "field" : "play_count" } }}}}
}

Elasticsearch terms聚合不准确的问题相关推荐

  1. es 精确查询不模糊_ES系列17:Terms聚合结果不精确,怎么破?

     点击上方"方才编程",即可关注我! 写在前面 关于更新: 其实持续不断的输出,还是需要点东西的,不仅是知识点的学习和沉淀,更多是内驱力.学习一个知识点,梳理脑图,到demo的编写 ...

  2. 触类旁通Elasticsearch:聚合

    目录 一.聚合的结构 二.度量集合 三.桶型聚合 四.嵌套聚合 1. 多桶聚合 2. 单桶聚合 <Elasticsearch In Action>学习笔记. 熟悉SQL的用户一定对聚合不会 ...

  3. Elasticsearch之聚合分析

    聚合分析 官方文档https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html 英文 ...

  4. elasticsearch(7)聚合统计-分组聚合

    原文:https://blog.csdn.net/sz85850597/article/details/82858831 elasticsearch(7)聚合统计-分组聚合 2018年09月26日 2 ...

  5. elasticsearch aggregations_Elasticsearch聚合的嵌套桶如何排序

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:原创文章分类汇总及配套源码,涉及Java.Docker.K8S.Devops等 关于嵌套桶 在 ...

  6. elasticsearch实现类似京东的商品搜索效果(elasticsearch动态聚合)

    用到京东的对其搜索应该不会陌生,其搜索也是使用elasticsearch完成的,下图为一个搜索效果图: 搜索筛选条件会根据查询返回的结果动态变化,要实现这个功能就要用到elasticsearch的聚合 ...

  7. Elasticsearch(9) --- 聚合查询(Bucket聚合)

    Elasticsearch(9) --- 聚合查询(Bucket聚合) 系统小说 www.kuwx.net 上一篇讲了Elasticsearch聚合查询中的Metric聚合:Elasticsearch ...

  8. Elasticsearch系列---聚合查询原理

    概要 本篇主要介绍聚合查询的内部原理,正排索引是如何建立的和优化的,fielddata的使用,最后简单介绍了聚合分析时如何选用深度优先和广度优先. 正排索引 聚合查询的内部原理是什么,Elastich ...

  9. java中addrange_java elasticsearch 桶聚合(bucket)

    Elasticsearch桶聚合,目的就是数据分组,先将数据按指定的条件分成多个组,然后对每一个组进行统计. 不了解Elasticsearch桶聚合概念,可以先学习下Elasticsearch桶聚合教 ...

最新文章

  1. Maya初学者完整的3D动画大师班视频教程
  2. 你不得不会的MarkDown--手把手教你掌握MarkDown
  3. 百度线下赛道报名通知!
  4. Log4j的isdebugEnabled的作用
  5. kafka系列文章索引
  6. 自己写js库,怎么支持AMD
  7. java类体_计算机二级考试Java类之类声明以及类体
  8. Socket网络编程--小小网盘程序(2)
  9. 【script】python 中文汉字与url的转换
  10. 不仅仅于 Json和XML ,快来学习Google出品的序列化神器Protocol Buffer
  11. Go一个协程实现加法demo
  12. tomcat是什么_为什么开发者放弃了Tomcat,选择了Undertow?
  13. 黑马程序员 python 数据分析 代码_2020年最新版 5.0程序员 黑马python人工智能数据分析机器学习软件测试全栈开发...
  14. office和flash计算机课程,Powerpoint和Flash制作教学课件技巧
  15. scratch编程例子
  16. 【转】Sphinx速成指南
  17. curaengine linux编译,Cura Engine
  18. SQL基础知识整理—数据库相关基本概念
  19. PS中的画笔工具和修饰模式(画笔模式)
  20. python属于面向对象的还是面向过程的呀-python中的面向对象和面向过程

热门文章

  1. JTA(Java Transaction API)事务
  2. Elasticsearch实战之(商品搜索API实现)
  3. mysql foreach用法_mysql foreach 标签的使用
  4. 2023年,下班后可以做什么副业?
  5. IDEA自定义Generate POJOs.groovy数据表批量生成实体类
  6. 【Numpy金融领域的应用】伽玛分布和贝塔分布随机抽样——以债券违约率与回收率为分析对象
  7. TIA(Text Image Augmentation) + LtA(Learn to Augmentation):文本图像扩增工具 + 学习生成更有效的训练样本
  8. Linux中head和tail的区别,linux head和tail命令详解
  9. 06——驾校科目一考试系统——考试时间
  10. Route map应用策略路由(上)