【Elasticsearch】 Composite Aggregation 详解

1.什么是 Composite Aggregation?

Composite Aggregation 是 Elasticsearch 中的一种特殊聚合方式,适用于需要分页展示的聚合结果。它与传统的聚合方式不同,采用了基于游标的分页模型。这种聚合方式可以高效地处理多级聚合中的所有桶,并支持分页功能。

2.基本结构

一个典型的 Composite Aggregation 查询如下:

```json

GET /your_index_name/_search

{

  "size": 0,

  "aggs": {

    "my_composite_agg": {

      "composite": {

        "size": 10,

        "sources": [

          {

            "field1": {

              "terms": {

                "field": "your_field_name1"

              }

            }

          },

          {

            "field2": {

              "terms": {

                "field": "your_field_name2"

              }

            }

          }

        ]

      }

    }

  }

}

```

在上述查询中:

• `sources`定义了按哪些字段分组,字段顺序决定了分组键(bucket key)的生成顺序。

• `size`定义每页的桶数量。

• 响应结果中的`after_key`用于获取下一页数据。

3.分页机制

Composite Aggregation 的分页机制通过`after`参数实现。每次查询返回指定数量的桶,并通过`after_key`提供下一页的游标。这种方式可以确保分页查询中数据无重复、无遗漏。

例如:

```json

GET /your_index_name/_search

{

  "size": 0,

  "aggs": {

    "my_composite_agg": {

      "composite": {

        "size": 10,

        "sources": [

          {

            "field1": {

              "terms": {

                "field": "your_field_name1"

              }

            }

          }

        ],

        "after": {

          "field1": "last_value_of_field1"

        }

      }

    }

  }

}

``

4.排序和方向

Composite Aggregation 支持对每个值源进行排序,可以通过设置`order`参数为`asc`(升序)或`desc`(降序)。

```json

GET /your_index_name/_search

{

  "size": 0,

  "aggs": {

    "my_composite_agg": {

      "composite": {

        "size": 10,

        "sources": [

          {

            "field1": {

              "terms": {

                "field": "your_field_name1",

                "order": "desc"

              }

            }

          },

          {

            "field2": {

              "terms": {

                "field": "your_field_name2",

                "order": "asc"

              }

            }

          }

        ]

      }

    }

  }

}

```

5.处理缺失值

默认情况下,缺少指定字段值的文档会被忽略。通过设置`missing_bucket`参数为`true`,可以将这些文档包含在响应中。

```json

GET /your_index_name/_search

{

  "size": 0,

  "aggs": {

    "my_composite_agg": {

      "composite": {

        "size": 10,

        "sources": [

          {

            "field1": {

              "terms": {

                "field": "your_field_name1",

                "missing_bucket": true

              }

            }

          }

        ]

      }

    }

  }

}

```

6.性能优化

Composite Aggregation 的设计特别适合大规模数据的聚合和分页,是传统`from + size`分页方法的高效替代方案。为了进一步优化性能,建议在索引中设置索引排序,使其与复合聚合中的源顺序部分或完全匹配。

7.应用场景

Composite Aggregation 适用于以下场景:

• 需要分页展示聚合结果。

• 处理大规模数据时,需要高效分页和排序。

• 需要对多个字段进行分组和聚合。

通过上述特性,Composite Aggregation 提供了一种强大且灵活的方式来处理复杂的聚合需求,特别是在需要分页和排序的场景中表现出色。

好的,下面我将通过一个具体的例子来展示如何使用 Composite Aggregation 来实现分页聚合查询。假设我们有一个电商数据集,其中包含商品的销售记录,我们希望按日期和商品类别进行分组,并计算每个分组的销售总额。

数据示例

假设我们的索引名为`sales`,其中的文档如下:

```json

{

  "timestamp": "2024-01-01T00:00:00Z",

  "product": "T-shirt",

  "category": "Clothing",

  "price": 20

}

 

{

  "timestamp": "2024-01-01T00:00:00Z",

  "product": "Jeans",

  "category": "Clothing",

  "price": 40

}

 

{

  "timestamp": "2024-01-02T00:00:00Z",

  "product": "T-shirt",

  "category": "Clothing",

  "price": 20

}

 

{

  "timestamp": "2024-01-02T00:00:00Z",

  "product": "Laptop",

  "category": "Electronics",

  "price": 1000

}

```

查询目标

我们希望按日期和商品类别进行分组,并计算每个分组的销售总额。同时,我们希望分页显示结果,每页显示 2 个分组。

第一页查询

首先,我们查询第一页的结果:

```json

GET /sales/_search

{

  "size": 0,

  "aggs": {

    "sales_by_date_and_category": {

      "composite": {

        "size": 2,

        "sources": [

          {

            "date": {

              "date_histogram": {

                "field": "timestamp",

                "calendar_interval": "1d"

              }

            }

          },

          {

            "category": {

              "terms": {

                "field": "category"

              }

            }

          }

        ]

      },

      "aggregations": {

        "total_sales": {

          "sum": {

            "field": "price"

          }

        }

      }

    }

  }

}

```

解释

• `size`:每页返回的分组数量。

• `sources`:定义了两个分组字段:

• `date`:按日期分组,每天一个桶。

• `category`:按商品类别分组。

• `aggregations`:在每个复合桶中计算销售总额。

查询结果

返回的结果如下:

```json

{

  "aggregations": {

    "sales_by_date_and_category": {

      "after_key": {

        "date": 1704115200000,

        "category": "Clothing"

      },

      "buckets": [

        {

          "key": {

            "date": 1704028800000,

            "category": "Clothing"

          },

          "doc_count": 2,

          "total_sales": {

            "value": 60

          }

        },

        {

          "key": {

            "date": 1704115200000,

            "category": "Clothing"

          },

          "doc_count": 1,

          "total_sales": {

            "value": 20

          }

        }

      ]

    }

  }

}

```

解释

• `buckets`:包含两个分组:

• 第一个分组:`2024-01-01`的`Clothing`类别,销售总额为 60。

• 第二个分组:`2024-01-02`的`Clothing`类别,销售总额为 20。

• `after_key`:提供了下一页的游标。

第二页查询

使用`after_key`查询下一页的结果:

```json

GET /sales/_search

{

  "size": 0,

  "aggs": {

    "sales_by_date_and_category": {

      "composite": {

        "size": 2,

        "sources": [

          {

            "date": {

              "date_histogram": {

                "field": "timestamp",

                "calendar_interval": "1d"

              }

            }

          },

          {

            "category": {

              "terms": {

                "field": "category"

              }

            }

          }

        ],

        "after": {

          "date": 1704115200000,

          "category": "Clothing"

        }

      },

      "aggregations": {

        "total_sales": {

          "sum": {

            "field": "price"

          }

        }

      }

    }

  }

}

``

查询结果

返回的结果如下:

```json

{

  "aggregations": {

    "sales_by_date_and_category": {

      "after_key": {

        "date": 1704115200000,

        "category": "Electronics"

      },

      "buckets": [

        {

          "key": {

            "date": 1704115200000,

            "category": "Electronics"

          },

          "doc_count": 1,

          "total_sales": {

            "value": 1000

          }

        }

      ]

    }

  }

}

``

解释

• `buckets`:包含一个分组:

• `2024-01-02`的`Electronics`类别,销售总额为 1000。

• `after_key`:提供了下一页的游标。

通过这种方式,我们可以高效地分页查询聚合结果,而不会遗漏或重复任何数据。

好的,接下来我们继续探讨如何处理更多分页结果,以及如何优化和扩展这个查询。

继续分页查询

假设我们继续查询下一页,使用上一页返回的`after_key`:

```json

GET /sales/_search

{

  "size": 0,

  "aggs": {

    "sales_by_date_and_category": {

      "composite": {

        "size": 2,

        "sources": [

          {

            "date": {

              "date_histogram": {

                "field": "timestamp",

                "calendar_interval": "1d"

              }

            }

          },

          {

            "category": {

              "terms": {

                "field": "category"

              }

            }

          }

        ],

        "after": {

          "date": 1704115200000,

          "category": "Electronics"

        }

      },

      "aggregations": {

        "total_sales": {

          "sum": {

            "field": "price"

          }

        }

      }

    }

  }

}

```

查询结果

如果返回结果为空,说明已经到达最后一页:

```json

{

  "aggregations": {

    "sales_by_date_and_category": {

      "buckets": []

    }

  }

}

``

这表明所有分组已经查询完毕。

性能优化

为了进一步优化性能,可以考虑以下几点:

1. 设置合理的`size`参数:根据实际需求设置合适的分页大小,避免过大或过小。

2. 索引排序:如果数据量很大,可以在索引创建时设置索引排序,使其与聚合的字段顺序一致。例如:

```json

   PUT /sales

   {

     "settings": {

       "index": {

         "sort.field": ["timestamp", "category"],

         "sort.order": ["asc", "asc"]

       }

     }

   }

   ```

3. 禁用`track_total_hits`:在分页查询中,通常不需要统计总命中数,可以通过设置`track_total_hits: false`来节省资源。

扩展应用

Composite Aggregation 不仅可以用于分页查询,还可以结合其他聚合功能,例如:

• 计算平均值:在每个分组中计算平均销售额。

```json

  "aggregations": {

    "average_sales": {

      "avg": {

        "field": "price"

      }

    }

  }

  ```

• 多级分组:可以增加更多分组字段,例如按地区分组。

```json

  "sources": [

    {

      "date": {

        "date_histogram": {

          "field": "timestamp",

          "calendar_interval": "1d"

        }

      }

    },

    {

      "category": {

        "terms": {

          "field": "category"

        }

      }

    },

    {

      "region": {

        "terms": {

          "field": "region"

        }

      }

    }

  ]

  ```

总结

通过 Composite Aggregation,我们可以高效地实现分页聚合查询,避免了传统分页方法(如`from + size`)在大规模数据下的性能瓶颈。同时,它还支持灵活的排序、多级分组和子聚合功能,能够满足复杂的业务需求。

 

以下是使用`composite aggregation`结合`terms`、`histogram`、`date_histogram`和`geotile_grid`的示例:

1.`terms`类型的`composite aggregation`

以下示例对`authors`索引中的`author_name`字段进行`terms`聚合:

```json

GET authors/_search

{

  "size": 0,

  "aggs": {

    "our_buckets": {

      "composite": {

        "sources": [

          { "authors": { "terms": { "field": "author_name" } } }

        ]

      }

    }

  }

}

```

2.`histogram`类型的`composite aggregation`

以下示例对`authors`索引中的`books_number`字段进行`histogram`聚合,区间设置为5:

```json

GET authors/_search

{

  "size": 0,

  "aggs": {

    "our_buckets": {

      "composite": {

        "sources": [

          { "booksnum": { "histogram": { "field": "books_number", "interval": 5 } } }

        ]

      }

    }

  }

}

```

3.`date_histogram`类型的`composite aggregation`

以下示例对`books`索引中的`publish_date`字段进行`date_histogram`聚合,时间间隔设置为一周:

```json

GET books/_search

{

  "size": 0,

  "aggs": {

    "our_buckets": {

      "composite": {

        "sources": [

          { "week": { "date_histogram": { "field": "publish_date", "calendar_interval": "1w" } } }

        ]

      }

    }

  }

}

```

4.`geotile_grid`类型的`composite aggregation`

以下示例对`authors`索引中的`authors_location`字段进行`geotile_grid`聚合,精度设置为6:

```json

GET authors/_search

{

  "size": 0,

  "aggs": {

    "our_buckets": {

      "composite": {

        "sources": [

          { "authorsloc": { "geotile_grid": { "field": "authors_location", "precision": 6 } } }

        ]

      }

    }

  }

}

```

5.组合使用多种聚合类型

以下示例同时使用`date_histogram`和`terms`聚合:

```json

GET books/_search

{

  "size": 0,

  "aggs": {

    "our_buckets": {

      "composite": {

        "sources": [

          { "week": { "date_histogram": { "field": "publish_date", "calendar_interval": "1w" } } },

          { "authors": { "terms": { "field": "author_name" } } }

        ]

      }

    }

  }

}

```

这些示例展示了如何在`composite aggregation`中使用不同类型的聚合,以满足不同的数据分析需求。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/965199.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【PDF多区域识别】如何批量PDF指定多个区域识别改名,基于Windows自带的UWP的文字识别实现方案

海关在对进口货物进行查验时,需要核对报关单上的各项信息。对报关单 PDF 批量指定区域识别改名后,海关工作人员可以更高效地从文件名中获取关键信息,如货物来源地、申报价值等。例如文件名 “[原产国]_[申报价值].pdf”,有助于海关快速筛选重点查验对象,提高查验效率和监管…

用python实现进度条

前言 在Python中,可以使用多种方式实现进度条。以下是几种常见的进度条格式的实现方法: 1. 使用 tqdm 库 tqdm 是一个非常流行的库,可以轻松地在循环中显示进度条。 from tqdm import tqdm import time# 示例:简单的进度条 fo…

每日一题洛谷P5721 【深基4.例6】数字直角三角形c++

#include<iostream> using namespace std; int main() {int n;cin >> n;int t 1;for (int i 0; i < n; i) {for (int j 0; j < n - i; j) {printf("%02d",t);t;}cout << endl;}return 0; }

Python----Python高级(并发编程:进程Process,多进程,进程间通信,进程同步,进程池)

一、进程Process 拥有自己独立的堆和栈&#xff0c;既不共享堆&#xff0c;也不共享栈&#xff0c;进程由操作系统调度&#xff1b;进程切换需要的资源很最大&#xff0c;效率低。 对于操作系统来说&#xff0c;一个任务就是一个进程&#xff08;Process&#xff09;&#xff…

Python 梯度下降法(六):Nadam Optimize

文章目录 Python 梯度下降法&#xff08;六&#xff09;&#xff1a;Nadam Optimize一、数学原理1.1 介绍1.2 符号定义1.3 实现流程 二、代码实现2.1 函数代码2.2 总代码 三、优缺点3.1 优点3.2 缺点 四、相关链接 Python 梯度下降法&#xff08;六&#xff09;&#xff1a;Nad…

《Kettle保姆级教学-界面介绍》

目录 一、Kettle介绍二、界面介绍1.界面构成2、菜单栏详细介绍2.1 【文件F】2.2 【编辑】2.3 【视图】2.4 【执行】2.5 【工具】2.6 【帮助】 3、转换界面介绍4、作业界面介绍5、执行结果 一、Kettle介绍 Kettle 是一个开源的 ETL&#xff08;Extract, Transform, Load&#x…

Spring Boot篇

为什么要用Spring Boot Spring Boot 优点非常多&#xff0c;如&#xff1a; 独立运行 Spring Boot 而且内嵌了各种 servlet 容器&#xff0c;Tomcat、Jetty 等&#xff0c;现在不再需要打成 war 包部署到 容器 中&#xff0c;Spring Boot 只要打成一个可执行的 jar 包就能独…

C# 中记录(Record)详解

从C#9.0开始&#xff0c;我们有了一个有趣的语法糖&#xff1a;记录(record)   为什么提供记录&#xff1f; 开发过程中&#xff0c;我们往往会创建一些简单的实体&#xff0c;它们仅仅拥有一些简单的属性&#xff0c;可能还有几个简单的方法&#xff0c;比如DTO等等&#xf…

Page Assist - 本地Deepseek模型 Web UI 的安装和使用

Page Assist Page Assist是一个开源的Chrome扩展程序&#xff0c;为本地AI模型提供一个直观的交互界面。通过它可以在任何网页上打开侧边栏或Web UI&#xff0c;与自己的AI模型进行对话&#xff0c;获取智能辅助。这种设计不仅方便了用户随时调用AI的能力&#xff0c;还保护了…

UE求职Demo开发日志#21 背包-仓库-装备栏移动物品

1 创建一个枚举记录来源位置 UENUM(BlueprintType) enum class EMyItemLocation : uint8 {None0,Bag UMETA(DisplayName "Bag"),Armed UMETA(DisplayName "Armed"),WareHouse UMETA(DisplayName "WareHouse"), }; 2 创建一个BagPad和WarePa…

Django框架丨从零开始的Django入门学习

Django 是一个用于构建 Web 应用程序的高级 Python Web 框架&#xff0c;Django是一个高度模块化的框架&#xff0c;使用 Django&#xff0c;只要很少的代码&#xff0c;Python 的程序开发人员就可以轻松地完成一个正式网站所需要的大部分内容&#xff0c;并进一步开发出全功能…

企业四要素如何用PHP进行调用

一、什么是企业四要素&#xff1f; 企业四要素接口是在企业三要素&#xff08;企业名称、统一社会信用代码、法定代表人姓名&#xff09;的基础上&#xff0c;增加了一个关键要素&#xff0c;通常是企业注册号或企业银行账户信息。这种接口主要用于更全面的企业信息验证&#x…

JVM监控和管理工具

基础故障处理工具 jps jps(JVM Process Status Tool)&#xff1a;Java虚拟机进程状态工具 功能 1&#xff1a;列出正在运行的虚拟机进程 2&#xff1a;显示虚拟机执行主类(main()方法所在的类) 3&#xff1a;显示进程ID(PID&#xff0c;Process Identifier) 命令格式 jps […

Java 大视界 -- Java 大数据在智慧文旅中的应用与体验优化(74)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

ASP.NET Core中间件Markdown转换器

目录 需求 文本编码检测 Markdown→HTML 注意 实现 需求 Markdown是一种文本格式&#xff1b;不被浏览器支持&#xff1b;编写一个在服务器端把Markdown转换为HTML的中间件。我们开发的中间件是构建在ASP.NET Core内置的StaticFiles中间件之上&#xff0c;并且在它之前运…

2025游戏行业的趋势预测

一、市场现状 从总产值的角度来看&#xff0c;游戏总产值的增长率已经放缓&#xff0c;由增量市场转化为存量市场&#xff0c;整体的竞争强度将会加大&#xff0c;技术水平不强&#xff08;开发技术弱、产品品质低、开发效率低&#xff09;的公司将会面临更大的生存的困难。 从…

C++的 I/O 流

本文把复杂的基类和派生类的作用和关系捋出来&#xff0c;具体的接口请参考相关文档 C的 I/O 流相关的类&#xff0c;继承关系如下图所示 https://zh.cppreference.com/w/cpp/io I / O 的概念&#xff1a;内存和外设进行数据交互称为 I / O &#xff0c;例如&#xff1a;把数…

在https下引用IC卡读卡器web插件

HTTPS &#xff08;全称&#xff1a;Hypertext Transfer Protocol Secure &#xff09;&#xff0c;是以安全为目标的 HTTP 通道&#xff0c;在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性 。HTTPS 在HTTP 的基础下加入SSL&#xff0c;HTTPS 的安全基础是 SSL&a…

堆的实现——堆的应用(堆排序)

文章目录 1.堆的实现2.堆的应用--堆排序 大家在学堆的时候&#xff0c;需要有二叉树的基础知识&#xff0c;大家可以看我的二叉树文章&#xff1a;二叉树 1.堆的实现 如果有⼀个关键码的集合 K {k0 , k1 , k2 , …&#xff0c;kn−1 } &#xff0c;把它的所有元素按完全⼆叉树…

基于单片机的智能安全插座(论文+源码)

1 系统整体方案设计 本课题基于单片机的智能安全插座设计&#xff0c;以STM32嵌入式单片机为主体&#xff0c;将计算机技术和检测技术有机结合&#xff0c;设计一款电量参数采集装置&#xff0c;实现电压、电流信号的数据采集任务&#xff0c;电压、电流和功率在上位机的显示任…