聚合编辑

聚合将您的数据汇总为指标、统计信息或其他分析结果。聚合可以帮助您回答以下问题:

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

Elasticsearch 将聚合组织成三个类别:

  • 指标 聚合,从字段值计算指标,例如总和或平均值。
  • 聚合,根据字段值、范围或其他条件将文档分组到桶中,也称为箱。
  • 管道 聚合,从其他聚合而不是文档或字段中获取输入。

运行聚合编辑

您可以通过指定 搜索搜索 APIaggs 参数,在搜索中运行聚合。以下搜索在 my-field 上运行 术语聚合

response = client.search(
  index: 'my-index-000001',
  body: {
    aggregations: {
      "my-agg-name": {
        terms: {
          field: 'my-field'
        }
      }
    }
  }
)
puts response
GET /my-index-000001/_search
{
  "aggs": {
    "my-agg-name": {
      "terms": {
        "field": "my-field"
      }
    }
  }
}

聚合结果位于响应的 aggregations 对象中

{
  "took": 78,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 5,
      "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [...]
  },
  "aggregations": {
    "my-agg-name": {                           
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": []
    }
  }
}

my-agg-name 聚合的结果。

更改聚合的范围编辑

使用 query 参数来限制运行聚合的文档

response = client.search(
  index: 'my-index-000001',
  body: {
    query: {
      range: {
        "@timestamp": {
          gte: 'now-1d/d',
          lt: 'now/d'
        }
      }
    },
    aggregations: {
      "my-agg-name": {
        terms: {
          field: 'my-field'
        }
      }
    }
  }
)
puts response
GET /my-index-000001/_search
{
  "query": {
    "range": {
      "@timestamp": {
        "gte": "now-1d/d",
        "lt": "now/d"
      }
    }
  },
  "aggs": {
    "my-agg-name": {
      "terms": {
        "field": "my-field"
      }
    }
  }
}

仅返回聚合结果编辑

默认情况下,包含聚合的搜索将返回搜索命中和聚合结果。要仅返回聚合结果,请将 size 设置为 0

response = client.search(
  index: 'my-index-000001',
  body: {
    size: 0,
    aggregations: {
      "my-agg-name": {
        terms: {
          field: 'my-field'
        }
      }
    }
  }
)
puts response
GET /my-index-000001/_search
{
  "size": 0,
  "aggs": {
    "my-agg-name": {
      "terms": {
        "field": "my-field"
      }
    }
  }
}

运行多个聚合编辑

您可以在同一个请求中指定多个聚合

response = client.search(
  index: 'my-index-000001',
  body: {
    aggregations: {
      "my-first-agg-name": {
        terms: {
          field: 'my-field'
        }
      },
      "my-second-agg-name": {
        avg: {
          field: 'my-other-field'
        }
      }
    }
  }
)
puts response
GET /my-index-000001/_search
{
  "aggs": {
    "my-first-agg-name": {
      "terms": {
        "field": "my-field"
      }
    },
    "my-second-agg-name": {
      "avg": {
        "field": "my-other-field"
      }
    }
  }
}

运行子聚合编辑

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

response = client.search(
  index: 'my-index-000001',
  body: {
    aggregations: {
      "my-agg-name": {
        terms: {
          field: 'my-field'
        },
        aggregations: {
          "my-sub-agg-name": {
            avg: {
              field: 'my-other-field'
            }
          }
        }
      }
    }
  }
)
puts response
GET /my-index-000001/_search
{
  "aggs": {
    "my-agg-name": {
      "terms": {
        "field": "my-field"
      },
      "aggs": {
        "my-sub-agg-name": {
          "avg": {
            "field": "my-other-field"
          }
        }
      }
    }
  }
}

响应将子聚合结果嵌套在其父聚合下

{
  ...
  "aggregations": {
    "my-agg-name": {                           
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "foo",
          "doc_count": 5,
          "my-sub-agg-name": {                 
            "value": 75.0
          }
        }
      ]
    }
  }
}

父聚合 my-agg-name 的结果。

my-agg-name 的子聚合 my-sub-agg-name 的结果。

添加自定义元数据编辑

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

response = client.search(
  index: 'my-index-000001',
  body: {
    aggregations: {
      "my-agg-name": {
        terms: {
          field: 'my-field'
        },
        meta: {
          "my-metadata-field": 'foo'
        }
      }
    }
  }
)
puts response
GET /my-index-000001/_search
{
  "aggs": {
    "my-agg-name": {
      "terms": {
        "field": "my-field"
      },
      "meta": {
        "my-metadata-field": "foo"
      }
    }
  }
}

响应将在适当位置返回 meta 对象

{
  ...
  "aggregations": {
    "my-agg-name": {
      "meta": {
        "my-metadata-field": "foo"
      },
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": []
    }
  }
}

返回聚合类型编辑

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

response = client.search(
  index: 'my-index-000001',
  typed_keys: true,
  body: {
    aggregations: {
      "my-agg-name": {
        histogram: {
          field: 'my-field',
          interval: 1000
        }
      }
    }
  }
)
puts response
GET /my-index-000001/_search?typed_keys
{
  "aggs": {
    "my-agg-name": {
      "histogram": {
        "field": "my-field",
        "interval": 1000
      }
    }
  }
}

响应将聚合类型作为聚合名称的前缀返回。

某些聚合返回的聚合类型与请求中的类型不同。例如,术语、显著术语百分位数 聚合将根据聚合字段的数据类型返回不同的聚合类型。

{
  ...
  "aggregations": {
    "histogram#my-agg-name": {                 
      "buckets": []
    }
  }
}

聚合类型 histogram,后跟 # 分隔符和聚合名称 my-agg-name

在聚合中使用脚本编辑

当字段与您需要的聚合不完全匹配时,您应该在 运行时字段 上进行聚合

GET /my-index-000001/_search?size=0
{
  "runtime_mappings": {
    "message.length": {
      "type": "long",
      "script": "emit(doc['message.keyword'].value.length())"
    }
  },
  "aggs": {
    "message_length": {
      "histogram": {
        "interval": 10,
        "field": "message.length"
      }
    }
  }
}

脚本动态计算字段值,这会给聚合增加一些开销。除了计算时间外,某些聚合(如 termsfilters)无法在使用运行时字段时使用其某些优化。总的来说,使用运行时字段的性能成本因聚合而异。

聚合缓存编辑

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

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

long 值的限制编辑

在运行聚合时,Elasticsearch 使用 double 值来保存和表示数字数据。因此,对大于 253long 数字的聚合是近似的。