背景

在对ES某个筛选字段聚合查询,类似groupBy操作后,发现该字段新增的数据,聚合结果没有展示出来,但是用户在全文检索新增的筛选数据后,又可以查询出来, 针对该问题进行了相关排查。

排查思路

首先要明确我们数据的写入流程, 下图:

在检查Mysql库的数据没有问题之后,开始检查ES是否有问题,根据现象我们知道既然在全文检索中都能搜索到,说明数据肯定是写入ES里了,但是又如何确定聚合结果呢?

首先添加日志将代码最终生成DSL语句打印出来

  1. LOGGER.info("\n{}", searchRequestBuilder);

这样就很方便地使用curl命令进行调试了

下面是对生成的DSL语句执行查询:

  1. curl -XGET 'http://ip:9200/es_data_index/_search?pretty' -H 'Content-Type: application/json' -d'
  2. {
  3. "query":{
  4. "bool":{
  5. "must":[
  6. {
  7. "term":{
  8. "companyId":{
  9. "value":1,
  10. "boost":1
  11. }
  12. }
  13. },
  14. {
  15. "term":{
  16. "yn":{
  17. "value":1,
  18. "boost":1
  19. }
  20. }
  21. },
  22. {
  23. "match_all":{
  24. "boost":1
  25. }
  26. }
  27. ],
  28. "must_not":[
  29. {
  30. "term":{
  31. "table_sentinel":{
  32. "value":2,
  33. "boost":1
  34. }
  35. }
  36. }
  37. ],
  38. "disable_coord":false,
  39. "adjust_pure_negative":true,
  40. "boost":1
  41. }
  42. },
  43. "aggregations":{
  44. "group_by_topics":{
  45. "terms":{
  46. "field":"topic",
  47. "size":10,
  48. "min_doc_count":1,
  49. "shard_min_doc_count":0,
  50. "show_term_doc_count_error":false,
  51. "order":[
  52. {
  53. "_count":"desc"
  54. },
  55. {
  56. "_term":"asc"
  57. }
  58. ]
  59. }
  60. }
  61. }
  62. }'

上图group_by_topics 就是我们要聚合的字段, 下面是执行该DSL语句的结果:

  1. "aggregations" : {
  2. "group_by_topics" : {
  3. "doc_count_error_upper_bound" : 0,
  4. "sum_other_doc_count" : 14,
  5. "buckets" : [
  6. {
  7. "key" : 1,
  8. "doc_count" : 35
  9. },
  10. {
  11. "key" : 19,
  12. "doc_count" : 25
  13. },
  14. {
  15. "key" : 18,
  16. "doc_count" : 17
  17. },
  18. {
  19. "key" : 29,
  20. "doc_count" : 15
  21. },
  22. {
  23. "key" : 20,
  24. "doc_count" : 12
  25. },
  26. {
  27. "key" : 41,
  28. "doc_count" : 8
  29. },
  30. {
  31. "key" : 161,
  32. "doc_count" : 5
  33. },
  34. {
  35. "key" : 2,
  36. "doc_count" : 3
  37. },
  38. {
  39. "key" : 3,
  40. "doc_count" : 2
  41. },
  42. {
  43. "key" : 21,
  44. "doc_count" : 2
  45. }
  46. ]
  47. }
  48. }

经过观察发现聚合结果确实没有我们新增的筛选项, 同时返回的数据只有10条

"sum_other_doc_count" : 14, 这项是关键项,从字面意思看还有有其他的文档,于是查询具体在ES中的意义是什么?

经过查询发现有段描述:

就是只会返回top结果, 部分结果不响应返回

那如何让这部分结果返回呢?

带着问题, 发现使用桶聚合,默认会根据doc_count 降序排序,同时默认只返回10条聚合结果.

可以通过在聚合查询增大属性size来解决,如下

  1. curl -XGET 'http://ip:9200/es_data_index/_search?pretty' -H 'Content-Type: application/json' -d'
  2. {
  3. "query":{
  4. "bool":{
  5. "must":[
  6. {
  7. "term":{
  8. "companyId":{
  9. "value":1,
  10. "boost":1
  11. }
  12. }
  13. },
  14. {
  15. "term":{
  16. "yn":{
  17. "value":1,
  18. "boost":1
  19. }
  20. }
  21. },
  22. {
  23. "match_all":{
  24. "boost":1
  25. }
  26. }
  27. ],
  28. "must_not":[
  29. {
  30. "term":{
  31. "table_sentinel":{
  32. "value":2,
  33. "boost":1
  34. }
  35. }
  36. }
  37. ],
  38. "disable_coord":false,
  39. "adjust_pure_negative":true,
  40. "boost":1
  41. }
  42. },
  43. "aggregations":{
  44. "group_by_topics":{
  45. "terms":{
  46. "field":"topic",
  47. "size":100,
  48. "min_doc_count":1,
  49. "shard_min_doc_count":0,
  50. "show_term_doc_count_error":false,
  51. "order":[
  52. {
  53. "_count":"desc"
  54. },
  55. {
  56. "_term":"asc"
  57. }
  58. ]
  59. }
  60. }
  61. }
  62. }'

下面是查询结果:

  1. "aggregations" : {
  2. "group_by_topics" : {
  3. "doc_count_error_upper_bound" : 0,
  4. "sum_other_doc_count" : 0,
  5. "buckets" : [
  6. {
  7. "key" : 1,
  8. "doc_count" : 35
  9. },
  10. {
  11. "key" : 19,
  12. "doc_count" : 25
  13. },
  14. {
  15. "key" : 18,
  16. "doc_count" : 17
  17. },
  18. {
  19. "key" : 29,
  20. "doc_count" : 15
  21. },
  22. {
  23. "key" : 20,
  24. "doc_count" : 12
  25. },
  26. {
  27. "key" : 41,
  28. "doc_count" : 8
  29. },
  30. {
  31. "key" : 161,
  32. "doc_count" : 5
  33. },
  34. {
  35. "key" : 2,
  36. "doc_count" : 3
  37. },
  38. {
  39. "key" : 3,
  40. "doc_count" : 2
  41. },
  42. {
  43. "key" : 21,
  44. "doc_count" : 2
  45. },
  46. {
  47. "key" : 81,
  48. "doc_count" : 2
  49. },
  50. {
  51. "key" : 801,
  52. "doc_count" : 2
  53. },
  54. {
  55. "key" : 0,
  56. "doc_count" : 1
  57. },
  58. {
  59. "key" : 4,
  60. "doc_count" : 1
  61. },
  62. {
  63. "key" : 5,
  64. "doc_count" : 1
  65. },
  66. {
  67. "key" : 6,
  68. "doc_count" : 1
  69. },
  70. {
  71. "key" : 7,
  72. "doc_count" : 1
  73. },
  74. {
  75. "key" : 11,
  76. "doc_count" : 1
  77. },
  78. {
  79. "key" : 23,
  80. "doc_count" : 1
  81. },
  82. {
  83. "key" : 28,
  84. "doc_count" : 1
  85. },
  86. {
  87. "key" : 201,
  88. "doc_count" : 1
  89. },
  90. {
  91. "key" : 241,
  92. "doc_count" : 1
  93. }
  94. ]
  95. }

把ES所有的筛选项数据都统计返回来.

代码里设置size:

  1. TermsAggregationBuilder termAgg1 = AggregationBuilders.terms("group_by_topics")
  2. .field("topic").size(100);

我们解决了问题, 现在思考下ES为什么不一下子返回所有统计项的结果数据呢?

答案是由ES聚合机制决定, ES怎么聚合呢

接受客户端的节点是协调节点

协调节点上,搜索任务会被分解成两个阶段: query和fetch

真正搜索或聚合任务的节点为数据节点,如图 2, 3, 4

聚合步骤:

  • 客户端发请求到协调节点
  • 协调节点将请求推送到各数据节点
  • 各数据节点指定分片参与数据汇集工作
  • 协调节点进行总结果汇聚

es 出于效率和性能原因等,聚合的结果其实是不精确的.什么意思? 就是以我们上面遇到的场景为例:

默认返回top 10 聚合结果, 首先各节点分片取自己的topic 10 返回给协调节点,然后协调节点进行汇总. 这样会导致全量的实际聚合结果跟预期的不一致.

这里扩展下,虽然有很多办法提高ES聚合精准度,但是对于大数据量的精准聚合,响应速度要快场景,es并不擅长,需要使用类似clickhouse这样的产品来解决这样的场景.

总结

本文主要针对实际工作的应用问题,来排查解决ES聚合数据部分数据未展示问题, 同时对ES的聚合检索原理进行讲解 .在数据量大、聚合精度要求高、响应速度快的业务场景ES并不擅长.

参考

https://discuss.elastic.co/t/what-does-sum-other-doc-count-mean-exactly/159687

https://stackoverflow.com/questions/22927098/show-all-elasticsearch-aggregation-results-buckets-and-not-just-10

[Elasticsearch] ES聚合场景下部分结果数据未返回问题分析的更多相关文章

  1. mock以及特殊场景下对mock数据的处理

    一.为什么要mock 工作中遇到以下问题,我们可以使用mock解决: 无法控制第三方系统某接口的返回,返回的数据不满足要求 某依赖系统还未开发完成,就需要对被测系统进行测试 有些系统不支持重复请求,或 ...

  2. 记一次高并发场景下.net监控程序数据上报的性能调优

    最近在和小伙伴们做充电与通信程序的架构迁移.迁移前的架构是,通信程序负责接收来自充电集控设备的数据实时数据,通过Thrift调用后端的充电服务,充电服务收到响应后放到进程的Queue中,然后在管理线程 ...

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

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

  4. Android智能手机中各种音频场景下的audio data path

    上一篇文章(Android智能手机上的音频浅析)说本篇将详细讲解Android智能手机中各种音频场景下的音频数据流向,现在我们就开始.智能手机中音频的主要场景有音频播放.音频录制.语音通信等.不同场景 ...

  5. ES 24 - 如何通过Elasticsearch进行聚合检索 (分组统计)

    目录 1 普通聚合分析 1.1 直接聚合统计 1.2 先检索, 再聚合 1.3 扩展: fielddata和keyword的聚合比较 2 嵌套聚合 2.1 先分组, 再聚合统计 2.2 先分组, 再统 ...

  6. 「Elasticsearch」ES重建索引怎么才能做到数据无缝迁移呢?

    背景 众所周知,Elasticsearch是⼀个实时的分布式搜索引擎,为⽤户提供搜索服务.当我们决定存储某种数据,在创建索引的时候就需要将数据结构,即Mapping确定下来,于此同时索引的设定和很多固 ...

  7. 亿级流量场景下,大型架构设计实现【全文检索高级搜索---ElasticSearch篇】-- 中

    1.Elasticsearch的基础分布式架构: 1.Elasticsearch对复杂分布式机制的透明隐藏特性2.Elasticsearch的垂直扩容与水平扩容3.增减或减少节点时的数据rebalan ...

  8. 浅谈Vue不同场景下组件间的数据交流

    浅谈Vue不同场景下组件间的数据“交流”   Vue的官方文档可以说是很详细了.在我看来,它和react等其他框架文档一样,讲述的方式的更多的是“方法论”,而不是“场景论”,这也就导致了:我们在阅读完 ...

  9. HBase指定大量列集合的场景下并发拉取数据时卡住的问题排查

    最近遇到一例,HBase 指定大量列集合的场景下,并发拉取数据,应用卡住不响应的情形.记录一下. 问题背景 退款导出中,为了获取商品规格编码,需要从 HBase 表 T 里拉取对应的数据. T 对商品 ...

随机推荐

  1. 3 - 简单了解一下springboot中的yml语法 和 使用yml赋值

    1.简单了解yml语法 2.使用yml给实体类赋值 准备工作:导入依赖 <!-- 这个jar包就是为了实体类中使用@ConfigurationProperties(prefix = " ...

  2. ctfshow WEB入门 信息收集 1-20

    web1 题目:开发注释未及时删除 查看页面源代码即可 web2 题目:js把鼠标右键和f12屏蔽了 方法一: 禁用JavaScript 方法二: url前面加上view-source: web3 题 ...

  3. Spark(二十)【SparkSQL将CSV导入Kudu】

    目录 SparkSql 将CSV导入kudu pom 依赖 scala 代码 启动脚本 SparkSql 将CSV导入kudu pom 依赖 <properties> <spark. ...

  4. android Paint 详解

    /**     * Paint类介绍 * * Paint即画笔,在绘图过程中起到了极其重要的作用,画笔主要保存了颜色, * 样式等绘制信息,指定了如何绘制文本和图形,画笔对象有很多设置方法, * 大体 ...

  5. JDK1.8新特性(一): 接口的默认方法default

    前言 今天在学习mysql分区优化时,发现一个博客专家大神,对其发布的文章简单学习一下: 一:简介 我们通常所说的接口的作用是用于定义一套标准.约束.规范等,接口中的方法只声明方法的签名,不提供相应的 ...

  6. springboot热部署与监控

    一.热部署 添加依赖+Ctrl+F9 <dependency> <groupId>org.springframework.boot</groupId> <ar ...

  7. go channel 概述

    精髓 将资源读进内存-->共享内存,一个个进程/线程进行处理,这是常见模式.go channel 是一种直接在进程/线程之间传递资源的方式,即以通信来共享内存.这便是go的精髓. 扩展-一些名词 ...

  8. 【Java多线程】线程池-ThreadPoolExecutor

    ThreadPoolExecutor提供了四个构造方法: 我们以最后一个构造方法(参数最多的那个),对其参数进行解释: public ThreadPoolExecutor(int corePoolSi ...

  9. idea集成开发工具快捷键大全

    1  执行(run)                                                 alt+r 2  提示补全 (Class Name Completion)    ...

  10. java 注解的几大作用及使用方法详解

    初学者可以这样理解注解:想像代码具有生命,注解就是对于代码中某些鲜活个体的贴上去的一张标签.简化来讲,注解如同一张标签. 在未开始学习任何注解具体语法而言,你可以把注解看成一张标签.这有助于你快速地理 ...