IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Elasticsearch:Aggregation 简介 -> 正文阅读

[大数据]Elasticsearch:Aggregation 简介

Aggregation 在中文中也被称作聚合。简单地说,Elasticsearch 中的 aggregation 聚合将你的数据汇总为指标、统计数据或其他分析。聚合可帮助您回答以下问题:

  • 我的网站的平均加载时间是多少?
  • 根据交易量,谁是我最有价值的客户?
  • 什么会被认为是我网络上的大文件?
  • 每个产品类别有多少产品?

Elasticsearch 将聚合分为三类:

  • Metric 聚合:根据字段值计算指标,例如总和或平均值。
  • Bucket 聚合:根据字段值、范围或其他标准将文档分组到存储桶(也称为箱)中。
  • Pipeline 聚合:从其他聚合而不是文档或字段中获取输入,并计算新的聚合

在之前的文章 “Elasticsearch:aggregation 介绍” 我对它有一些介绍。在今天的文章中,我来对它做一个非常简单的介绍,以便大家对它有一个更加清楚明了的认识。

准备工作

我们首先需要参阅文章 “Elastic:开发者上手指南” 来安装自己的 Elasticsearch 及 Kibana:

你需要根据自己的平台选择合适的方式来安装。你可以选择最新的 Elastic Stack 8.2 来进行安装。

准备数据

接下来,我们先创建一个练习的数据。我们打开 Kibana,并导航至 Dev Tools:

?我们使用 _bulk API 来导入数据:

在 Console 中,我们输入如下的数据并执行:

PUT bank/_bulk
{ "create":{ } }
{ "account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL" }
{ "create":{ } }
{ "account_number":6,"balance":5686,"firstname":"Hattie","lastname":"Bond","age":36,"gender":"M","address":"671 Bristol Street","employer":"Netagy","email":"hattiebond@netagy.com","city":"Dante","state":"TN" }
{ "create":{ } }
{ "account_number":13,"balance":32838,"firstname":"Nanette","lastname":"Bates","age":28,"gender":"F","address":"789 Madison Street","employer":"Quility","email":"nanettebates@quility.com","city":"Nogal","state":"VA" }
{ "create":{ } }
{ "account_number":18,"balance":4180,"firstname":"Dale","lastname":"Adams","age":33,"gender":"M","address":"467 Hutchinson Court","employer":"Boink","email":"daleadams@boink.com","city":"Orick","state":"MD" }
{ "create":{ } }
{ "account_number":20,"balance":16418,"firstname":"Elinor","lastname":"Ratliff","age":36,"gender":"M","address":"282 Kings Place","employer":"Scentric","email":"elinorratliff@scentric.com","city":"Ribera","state":"WA" }
{ "create":{ } }
{ "account_number":25,"balance":40540,"firstname":"Virginia","lastname":"Ayala","age":39,"gender":"F","address":"171 Putnam Avenue","employer":"Filodyne","email":"virginiaayala@filodyne.com","city":"Nicholson","state":"PA" }
{ "create":{ } }
{ "account_number":32,"balance":48086,"firstname":"Dillard","lastname":"Mcpherson","age":34,"gender":"F","address":"702 Quentin Street","employer":"Quailcom","email":"dillardmcpherson@quailcom.com","city":"Veguita","state":"IN" }
{ "create":{ } }
{ "account_number":37,"balance":18612,"firstname":"Mcgee","lastname":"Mooney","age":39,"gender":"M","address":"826 Fillmore Place","employer":"Reversus","email":"mcgeemooney@reversus.com","city":"Tooleville","state":"OK" }
{ "create":{ } }
{ "account_number":44,"balance":34487,"firstname":"Aurelia","lastname":"Harding","age":37,"gender":"M","address":"502 Baycliff Terrace","employer":"Orbalix","email":"aureliaharding@orbalix.com","city":"Yardville","state":"DE" }
{ "create":{ } }
{ "account_number":49,"balance":29104,"firstname":"Fulton","lastname":"Holt","age":23,"gender":"F","address":"451 Humboldt Street","employer":"Anocha","email":"fultonholt@anocha.com","city":"Sunriver","state":"RI" }

?当我们执行完上面的指令后,我们就可以看到一个被创建的索引 bank,并且它里面含有 10 个文档:

GET bank/_count
{
  "count" : 10,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  }
}

接下来,为了让大家对 aggregation 有一个认识,我在下面来展示如何实现 aggregation 操作的。

在做聚合之前,我们先来了解我们的数据:

GET bank/_mapping
{
  "bank" : {
    "mappings" : {
      "properties" : {
        "account_number" : {
          "type" : "long"
        },
        "address" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "age" : {
          "type" : "long"
        },
        "balance" : {
          "type" : "long"
        },
        "city" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "email" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "employer" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "firstname" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "gender" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "lastname" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "state" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

从上面的展示中,我们可以看出来有的字段是 text 类型的,那么它不可以进行聚合,但是如果这个字段是 multi-field 的,并且它的一个字段是 keyword 的,那么它的 keyword 字段是可以进行聚合的。截止目前为止,除?text?和?annotated_text?类型的字段外,所有的其它类型的字段都支持聚合。

运行一个聚合

你可以通过指定搜索 API 的 aggs 参数将聚合作为搜索的一部分运行。 以下搜索在 city.keyword?上运行术语聚合:

GET bank/_search?filter_path=aggregations
{
  "size": 0,
  "aggs": {
    "cities_distribution": {
      "terms": {
        "field": "city.keyword",
        "size": 10
      }
    }
  }
}

在通常的情况下,我们设置 size 为 0,这样我们不需要返回任何的文档。它仅返回聚合的结果。这样做的好处是节省相应的负载,同时也可以缓存我们的响应,以便下次执行同样的聚合时,返回速度更快。上面命令返回的结果为:

{
  "aggregations" : {
    "cities_distribution" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "Brogan",
          "doc_count" : 1
        },
        {
          "key" : "Dante",
          "doc_count" : 1
        },
        {
          "key" : "Nicholson",
          "doc_count" : 1
        },
        {
          "key" : "Nogal",
          "doc_count" : 1
        },
        {
          "key" : "Orick",
          "doc_count" : 1
        },
        {
          "key" : "Ribera",
          "doc_count" : 1
        },
        {
          "key" : "Sunriver",
          "doc_count" : 1
        },
        {
          "key" : "Tooleville",
          "doc_count" : 1
        },
        {
          "key" : "Veguita",
          "doc_count" : 1
        },
        {
          "key" : "Yardville",
          "doc_count" : 1
        }
      ]
    }
  }
}

我们可以看到在各个城市的文档数。上面显示每个城市的文档数为 1。

改变聚合的范围

针对特别大的数据集来说,聚合是非常耗时的。我们可以通过查询来限定它的聚合文档的范围。我们可以这么来操作:

GET bank/_search?filter_path=aggregations
{
  "size": 0,
  "query": {
    "range": {
      "balance": {
        "gte": 4000,
        "lte": 10000
      }
    }
  }, 
  "aggs": {
    "cities_distribution": {
      "terms": {
        "field": "city.keyword",
        "size": 10
      }
    }
  }
}

在上面,我们通过设置一个查询的范围,限定 balance 在 4000 到 10000 之间的文档来进行聚合。这样聚合作用在一个小一点的文档集合中,在很多的情况下会运行更快。上面的命令返回的结果为:

{
  "aggregations" : {
    "cities_distribution" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "Dante",
          "doc_count" : 1
        },
        {
          "key" : "Orick",
          "doc_count" : 1
        }
      ]
    }
  }
}

运行多个集合

我们有时甚至可以在同一个请求中执行多个聚合:

GET bank/_search?filter_path=aggregations
{
  "size": 0,
  "aggs": {
    "cities_distribution": {
      "terms": {
        "field": "city.keyword",
        "size": 5
      }
    },
    "average_age": {
      "avg": {
        "field": "age"
      }
    }
  }
}

在上面,我们使用了两个聚合:一个求城市的文档分别及平均年龄。上面命令的结果为:

{
  "aggregations" : {
    "cities_distribution" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 5,
      "buckets" : [
        {
          "key" : "Brogan",
          "doc_count" : 1
        },
        {
          "key" : "Dante",
          "doc_count" : 1
        },
        {
          "key" : "Nicholson",
          "doc_count" : 1
        },
        {
          "key" : "Nogal",
          "doc_count" : 1
        },
        {
          "key" : "Orick",
          "doc_count" : 1
        }
      ]
    },
    "average_age" : {
      "value" : 33.7
    }
  }
}

运行 sub-aggregations

桶聚合支持桶或指标子聚合。 例如,具有 avg 子聚合的 histogram 聚合计算每个文档桶的平均值。 嵌套子聚合没有级别或深度限制。

GET bank/_search?filter_path=aggregations
{
  "size": 0,
  "aggs": {
    "balance_distribution": {
      "histogram": {
        "field": "balance",
        "interval": 5000
      },
      "aggs": {
        "average_age": {
          "avg": {
            "field": "age"
          }
        }
      }
    }
  }
}

上面的命令返回的结果为:

{
  "aggregations" : {
    "balance_distribution" : {
      "buckets" : [
        {
          "key" : 0.0,
          "doc_count" : 1,
          "average_age" : {
            "value" : 33.0
          }
        },
        {
          "key" : 5000.0,
          "doc_count" : 1,
          "average_age" : {
            "value" : 36.0
          }
        },
        {
          "key" : 10000.0,
          "doc_count" : 0,
          "average_age" : {
            "value" : null
          }
        },
        {
          "key" : 15000.0,
          "doc_count" : 2,
          "average_age" : {
            "value" : 37.5
          }
        },
        {
          "key" : 20000.0,
          "doc_count" : 0,
          "average_age" : {
            "value" : null
          }
        },
        {
          "key" : 25000.0,
          "doc_count" : 1,
          "average_age" : {
            "value" : 23.0
          }
        },
        {
          "key" : 30000.0,
          "doc_count" : 2,
          "average_age" : {
            "value" : 32.5
          }
        },
        {
          "key" : 35000.0,
          "doc_count" : 1,
          "average_age" : {
            "value" : 32.0
          }
        },
        {
          "key" : 40000.0,
          "doc_count" : 1,
          "average_age" : {
            "value" : 39.0
          }
        },
        {
          "key" : 45000.0,
          "doc_count" : 1,
          "average_age" : {
            "value" : 34.0
          }
        }
      ]
    }
  }
}

添加定制 metadata

使用 meta 元对象将自定义元数据与聚合相关联:

GET bank/_search?filter_path=aggregations
{
  "size": 0,
  "aggs": {
    "state_dist": {
      "terms": {
        "field": "state.keyword",
        "size": 5
      },
      "meta": {
        "my-metadata-field": "foo"
      }
    }
  }
}

在返回的结果中,我们可以看到 meta 对象:

{
  "aggregations" : {
    "state_dist" : {
      "meta" : {
        "my-metadata-field" : "foo"
      },
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 5,
      "buckets" : [
        {
          "key" : "DE",
          "doc_count" : 1
        },
        {
          "key" : "IL",
          "doc_count" : 1
        },
        {
          "key" : "IN",
          "doc_count" : 1
        },
        {
          "key" : "MD",
          "doc_count" : 1
        },
        {
          "key" : "OK",
          "doc_count" : 1
        }
      ]
    }
  }
}

返回聚合的类型

默认情况下,聚合结果包括聚合的名称,但不包括其类型。 要返回聚合类型,请使用 typed_keys 查询参数。

GET bank/_search?typed_keys&filter_path=aggregations
{
  "size": 0,
  "aggs": {
    "agg_dist": {
      "histogram": {
        "field": "age",
        "interval": 10
      }
    }
  }
}

上面的命令返回的结果为:

{
  "aggregations" : {
    "histogram#agg_dist" : {
      "buckets" : [
        {
          "key" : 20.0,
          "doc_count" : 2
        },
        {
          "key" : 30.0,
          "doc_count" : 8
        }
      ]
    }
  }
}

上面的结果显示是一个 histogram 的聚合。

使用 scripts 来进行聚合

当一个字段与你需要的聚合不完全匹配时,你应该在运行时字段(runtime field)上进行聚合:

GET bank/_search?filter_path=aggregations
{
  "size": 0,
  "runtime_mappings": {
    "name": {
      "type": "keyword",
      "script": {
        "source": "emit(doc['firstname.keyword'].value + ' ' + doc['lastname.keyword'].value)"
      }
    }
  }, 
  "aggs": {
    "name": {
      "terms": {
        "field": "name",
        "size": 5
      }
    }
  }
}

上面的命令返回的结果为:

{
  "aggregations" : {
    "name" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 5,
      "buckets" : [
        {
          "key" : "Amber Duke",
          "doc_count" : 1
        },
        {
          "key" : "Aurelia Harding",
          "doc_count" : 1
        },
        {
          "key" : "Dale Adams",
          "doc_count" : 1
        },
        {
          "key" : "Dillard Mcpherson",
          "doc_count" : 1
        },
        {
          "key" : "Elinor Ratliff",
          "doc_count" : 1
        }
      ]
    }
  }
}

在上面,我们把 firstname 和 lastname 一起加在一起,并对它进行统计。脚本动态计算字段值,这给聚合增加了一点开销。 除了计算所花费的时间之外,某些聚合(如 termsfilters)不能将它们的某些优化与运行时字段一起使用。 总的来说,使用运行时字段的性能成本因聚合而异。

聚合缓存

为了更快的响应,Elasticsearch 将频繁运行的聚合结果缓存在分片请求缓存中。 要获得缓存的结果,请为每次搜索使用相同的首选项字符串。 如果你不需要搜索命中,请将 size 设置为 0 以避免填充缓存。

Elasticsearch 将具有相同首选项字符串的搜索路由到相同的分片。 如果分片的数据在搜索之间没有变化,则分片返回缓存的聚合结果。

Long 类型值的限制

运行聚合时,Elasticsearch 使用双精度值来保存和表示数字数据。 因此,大于?2^23 的长数字的聚合是近似的。

更多阅读,请参阅 “Elastic:开发者上手指南” 中的 “Aggregations” 章节。

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-06-16 21:45:45  更:2022-06-16 21:46:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:28:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码