稀有分组聚合

稀有分组聚合 #

rare_terms 稀有分组聚合是一个分组聚合,用于识别数据集中的不常见词项。与 terms 聚合(查找最常见的词项)不同, rare_terms 聚合查找出现频率最低的词项。 rare_terms 聚合适用于异常检测、长尾分析和异常报告等应用。

可以使用 terms 通过按升序计数排序( “order”: {“count”: “asc”} )来搜索不常见的值。然而,我们强烈不建议这种做法,因为在涉及多个分片时,它可能导致不准确的结果。一个全局上不常见的词项可能不会在每个单个分片上显得不常见,或者可能完全不在某些分片返回的最不常见结果中。相反,一个在某个分片上出现频率较低的词项可能在另一个分片上很常见。在这两种情况下,分片级别的聚合可能会遗漏稀有词项,导致整体结果不正确。我们建议使用 rare_terms 聚合代替 terms 聚合,它专门设计用于更准确地处理这些情况。

近似结果 #

计算 rare_terms 聚合的精确结果需要编译所有分片上的值完整映射,这需要过多的运行时内存。因此, rare_terms 聚合结果被近似处理。

rare_terms 计算中的大多数错误是假阴性或“遗漏”的值,这些值定义了聚合检测测试的灵敏度。 rare_terms 聚合使用 CuckooFilter 算法以实现适当的灵敏度和可接受的内存使用平衡。有关 CuckooFilter 算法的描述,请参阅这篇论文。

控制灵敏度 #

rare_terms 聚合算法中的灵敏度误差被衡量为被遗漏的稀有值的比例,或 false negatives/target values 。例如,如果聚合在包含 5,000 个稀有值的数据集中遗漏了 100 个稀有值,灵敏度误差为 100/5000 = 0.02 ,或 2%。

您可以调整 precision 参数在 rare_terms 聚合中来控制灵敏度和内存使用之间的权衡。

这些因素也会影响灵敏度和内存的权衡:

  • 唯一值的总数
  • 数据集中稀有项的比例

以下指南可以帮助你决定使用哪个 precision 值。

计算内存使用 #

运行时内存使用以绝对值描述,通常以 RAM 的 MB 为单位。

内存使用随唯一项数量的增加而线性增长。线性扩展系数因 precision 参数而异,大致在每百万个唯一值 1.0 到 2.5 MB 之间。对于默认的 precision 设置为 0.001 时,内存成本约为每百万个唯一值 1.75 MB。

管理灵敏度误差 #

敏感性误差随唯一值总数的增加而线性增长。有关估算唯一值数量的信息,请参阅基数聚合。

在默认 precision 设置下,即使对于具有 1000 万至 2000 万个唯一值的集合,敏感性误差也极少超过 2.5%。对于 precision 设置为 0.00001 时,敏感性误差极少超过 0.6%。然而,非常低的稀有值绝对数量可能导致误差率出现较大波动(如果有两个稀有值,漏掉其中一个会导致 50% 的误差率)。

与其他聚合的兼容性 #

rare_terms 聚合使用广度优先收集模式,与某些子聚合和嵌套配置中需要深度优先收集模式的聚合不兼容。

参数说明 #

rare_terms 聚合采用以下参数。

参数必需/可选数据类型描述
field必填String用于分析稀有词的字段。必须是数值类型或具有 keyword 映射的文本类型。
max_doc_count可选Integer一个词被考虑为罕见词所需的最大文档数量。默认值是 1 。最大值是 100 。
precision可选Integer控制用于识别罕见词的算法的精确度。较高的值提供更精确的结果,但会消耗更多内存。默认值是 0.001 。最小(最精确的允许值)是 0.00001 。
include可选Array/regex结果中要包含的词。可以是正则表达式或值的数组。
exclude可选Array/regex从结果中排除的词项。可以是正则表达式或值数组。
missing可选String用于没有聚合字段值的文档的值。

参考样例 #

以下请求数据中仅出现一次的所有目的地机场代码:

GET sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "rare_destination": {
      "rare_terms": {
        "field": "DestAirportID",
        "max_doc_count": 1
      }
    }
  }
}

返回内容显示,有两个机场符合仅在数据中出现一次的标准:

{
  "took": 12,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 10000,
      "relation": "gte"
    },
    "max_score": null,
    "hits": []
  },
  "aggregations": {
    "rare_destination": {
      "buckets": [
        {
          "key": "ADL",
          "doc_count": 1
        },
        {
          "key": "BUF",
          "doc_count": 1
        }
      ]
    }
  }
}

文档数量限制 #

使用 max_doc_count 参数指定 rare_terms 聚合可以返回的最大文档数量。 rare_terms 返回的词项数量没有限制,因此较大的 max_doc_count 值可能会返回非常大的结果集。因此, 100 是允许的最大 max_doc_count 值。

以下请求数据中最多出现两次的所有目的地机场代码:

GET sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "rare_destination": {
      "rare_terms": {
        "field": "DestAirportID",
        "max_doc_count": 2
      }
    }
  }
}

响应显示,有七个目的地机场代码符合出现次数在两次或更少文档中的标准,包括前一个示例中的两个:

{
  "took": 6,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 10000,
      "relation": "gte"
    },
    "max_score": null,
    "hits": []
  },
  "aggregations": {
    "rare_destination": {
      "buckets": [
        {
          "key": "ADL",
          "doc_count": 1
        },
        {
          "key": "BUF",
          "doc_count": 1
        },
        {
          "key": "ABQ",
          "doc_count": 2
        },
        {
          "key": "AUH",
          "doc_count": 2
        },
        {
          "key": "BIL",
          "doc_count": 2
        },
        {
          "key": "BWI",
          "doc_count": 2
        },
        {
          "key": "MAD",
          "doc_count": 2
        }
      ]
    }
  }
}

过滤 (include 和 exclude) #

使用 includeexclude 参数来过滤 rare_terms 聚合返回的值。这两个参数可以在同一个聚合中包含。 exclude 过滤器具有优先级;任何被排除的值都会从结果中移除,无论它们是否被明确包含。

includeexclude 的参数可以是正则表达式(regex),包括字符串字面量,或数组。混合正则表达式和数组参数会导致错误。例如,以下组合是不允许的:

"rare_terms": {
  "field": "DestAirportID",
  "max_doc_count": 2,
  "exclude": ["ABQ", "AUH"],
  "include": "A.*"
}

示例:过滤 #

以下示例修改了前面的示例,以包含所有以“A”开头的机场代码,但排除“ABQ”机场代码:

GET sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "rare_destination": {
      "rare_terms": {
        "field": "DestAirportID",
        "max_doc_count": 2,
        "include": "A.*",
        "exclude": "ABQ"
      }
    }
  }
}

响应显示了符合过滤条件的那两个机场代码:

{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 10000,
      "relation": "gte"
    },
    "max_score": null,
    "hits": []
  },
  "aggregations": {
    "rare_destination": {
      "buckets": [
        {
          "key": "ADL",
          "doc_count": 1
        },
        {
          "key": "AUH",
          "doc_count": 2
        }
      ]
    }
  }
}

示例:使用数组输入进行过滤 #

以下示例数据中最多出现两次的 所有目的地机场代码,但指定了要排除的机场代码数组:

GET sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "rare_destination": {
      "rare_terms": {
        "field": "DestAirportID",
        "max_doc_count": 2,
        "exclude": ["ABQ", "BIL", "MAD"]
      }
    }
  }
}

响应中排除了排除的机场代码:

{
  "took": 6,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 10000,
      "relation": "gte"
    },
    "max_score": null,
    "hits": []
  },
  "aggregations": {
    "rare_destination": {
      "buckets": [
        {
          "key": "ADL",
          "doc_count": 1
        },
        {
          "key": "BUF",
          "doc_count": 1
        },
        {
          "key": "AUH",
          "doc_count": 2
        },
        {
          "key": "BWI",
          "doc_count": 2
        }
      ]
    }
  }
}