使用运行时字段更改数据源中的数据
Elastic Stack 无服务器
如果您使用数据源,则可以使用运行时字段在分析之前更改数据。您可以向数据源添加一个可选的 runtime_mappings
属性,您可以在其中指定字段类型和脚本,这些脚本评估自定义表达式,而不会影响您从中检索数据的索引。
如果您的数据源定义了运行时字段,您可以在异常检测作业中使用这些字段。例如,您可以在一个或多个检测器的分析函数中使用运行时字段。运行时字段可能会根据运行时脚本中定义的计算影响搜索性能。
这些示例中的一些使用正则表达式。默认情况下,正则表达式被禁用,因为它们规避了 Painless 针对长时间运行和消耗大量内存的脚本提供的保护。有关更多信息,请参阅Painless 脚本语言。
机器学习分析区分大小写。例如,“John”被认为与“john”不同。这就是您可能考虑使用脚本将字符串转换为大写或小写字母的原因之一。
- 示例 1:添加两个数值字段
- 示例 2:连接字符串
- 示例 3:修剪字符串
- 示例 4:将字符串转换为小写
- 示例 5:将字符串转换为混合大小写格式
- 示例 6:替换令牌
- 示例 7:正则表达式匹配和连接
- 示例 8:转换地理点数据
以下索引 API 创建并将内容添加到后续示例中使用的索引
PUT /my-index-000001
{
"mappings":{
"properties": {
"@timestamp": { "type": "date" },
"aborted_count": { "type": "long" },
"another_field": { "type": "keyword" },
"clientip": { "type": "keyword" },
"coords": {
"properties": {
"lat": { "type": "keyword" },
"lon": { "type": "keyword" }
}
},
"error_count": { "type": "long" },
"query": { "type": "keyword" },
"some_field": { "type": "keyword" },
"tokenstring1":{ "type":"keyword" },
"tokenstring2":{ "type":"keyword" },
"tokenstring3":{ "type":"keyword" }
}
}
}
PUT /my-index-000001/_doc/1
{
"@timestamp":"2017-03-23T13:00:00",
"error_count":36320,
"aborted_count":4156,
"some_field":"JOE",
"another_field":"SMITH ",
"tokenstring1":"foo-bar-baz",
"tokenstring2":"foo bar baz",
"tokenstring3":"foo-bar-19",
"query":"www.ml.elastic.co",
"clientip":"123.456.78.900",
"coords": {
"lat" : 41.44,
"lon":90.5
}
}
- 在此示例中,字符串字段映射为
keyword
字段以支持聚合。如果您想要同一字段的全文 (text
) 和关键字 (keyword
) 版本,请使用多字段。有关更多信息,请参阅 字段。
PUT _ml/anomaly_detectors/test1
{
"analysis_config":{
"bucket_span": "10m",
"detectors":[
{
"function":"mean",
"field_name": "total_error_count"
}
]
},
"data_description": {
"time_field":"@timestamp"
},
"datafeed_config":{
"datafeed_id": "datafeed-test1",
"indices": ["my-index-000001"],
"runtime_mappings": {
"total_error_count": {
"type": "long",
"script": {
"source": "emit(doc['error_count'].value + doc['aborted_count'].value)"
}
}
}
}
}
- 名为
total_error_count
的运行时字段在作业中的检测器中被引用。 - 运行时字段在数据源中定义。
这个 test1
异常检测作业包含一个检测器,该检测器在均值分析函数中使用运行时字段。datafeed-test1
数据源定义了运行时字段。它包含一个脚本,该脚本将文档中的两个字段相加,以产生“总”错误计数。
runtime_mappings
属性的语法与 Elasticsearch 使用的语法相同。有关更多信息,请参阅 运行时字段。
您可以使用以下 API 预览数据源的内容
GET _ml/datafeeds/datafeed-test1/_preview
在此示例中,API 返回以下结果,其中包含 error_count
和 aborted_count
值的总和
[
{
"@timestamp": 1490274000000,
"total_error_count": 40476
}
]
此示例演示如何使用运行时字段,但它包含的数据不足以生成有意义的结果。
或者,您可以使用 Kibana 创建使用运行时字段的高级异常检测作业。要将 runtime_mappings
属性添加到您的数据源,您必须使用 编辑 JSON 选项卡。例如

PUT _ml/anomaly_detectors/test2
{
"analysis_config":{
"bucket_span": "10m",
"detectors":[
{
"function":"low_info_content",
"field_name":"my_runtime_field"
}
]
},
"data_description": {
"time_field":"@timestamp"
},
"datafeed_config":{
"datafeed_id": "datafeed-test2",
"indices": ["my-index-000001"],
"runtime_mappings": {
"my_runtime_field": {
"type": "keyword",
"script": {
"source": "emit(doc['some_field'].value + '_' + doc['another_field'].value)"
}
}
}
}
}
GET _ml/datafeeds/datafeed-test2/_preview
- 在这种情况下,运行时字段具有通用名称,因为它用于示例中的各种测试。
- 运行时字段使用加号 (+) 运算符来连接字符串。
预览数据源 API 返回以下结果,这些结果表明 "JOE" 和 "SMITH " 已被连接并添加了下划线
[
{
"@timestamp": 1490274000000,
"my_runtime_field": "JOE_SMITH "
}
]
POST _ml/datafeeds/datafeed-test2/_update
{
"runtime_mappings": {
"my_runtime_field": {
"type": "keyword",
"script": {
"source": "emit(doc['another_field'].value.trim())"
}
}
}
}
GET _ml/datafeeds/datafeed-test2/_preview
- 此运行时字段使用
trim()
函数来修剪字符串中的多余空格。
预览数据源 API 返回以下结果,这些结果表明 "SMITH " 已被修剪为 "SMITH"
[
{
"@timestamp": 1490274000000,
"my_script_field": "SMITH"
}
]
POST _ml/datafeeds/datafeed-test2/_update
{
"runtime_mappings": {
"my_runtime_field": {
"type": "keyword",
"script": {
"source": "emit(doc['some_field'].value.toLowerCase())"
}
}
}
}
GET _ml/datafeeds/datafeed-test2/_preview
- 此运行时字段使用
toLowerCase
函数将字符串转换为全小写字母。同样,您可以使用toUpperCase
函数将字符串转换为大写字母。
预览数据源 API 返回以下结果,这些结果表明 "JOE" 已被转换为 "joe"
[
{
"@timestamp": 1490274000000,
"my_script_field": "joe"
}
]
POST _ml/datafeeds/datafeed-test2/_update
{
"runtime_mappings": {
"my_runtime_field": {
"type": "keyword",
"script": {
"source": "emit(doc['some_field'].value.substring(0, 1).toUpperCase() + doc['some_field'].value.substring(1).toLowerCase())"
}
}
}
}
GET _ml/datafeeds/datafeed-test2/_preview
- 此运行时字段是大小写操作的更复杂示例。它使用
subString()
函数将字符串的第一个字母大写,并将剩余字符转换为小写。
预览数据源 API 返回以下结果,这些结果表明 "JOE" 已被转换为 "Joe"
[
{
"@timestamp": 1490274000000,
"my_script_field": "Joe"
}
]
POST _ml/datafeeds/datafeed-test2/_update
{
"runtime_mappings": {
"my_runtime_field": {
"type": "keyword",
"script": {
"source": "emit(/\\s/.matcher(doc['tokenstring2'].value).replaceAll('_'))"
}
}
}
}
GET _ml/datafeeds/datafeed-test2/_preview
- 此脚本使用正则表达式将空格替换为下划线。
预览数据源 API 返回以下结果,这些结果表明 "foo bar baz" 已被转换为 "foo_bar_baz"
[
{
"@timestamp": 1490274000000,
"my_script_field": "foo_bar_baz"
}
]
POST _ml/datafeeds/datafeed-test2/_update
{
"runtime_mappings": {
"my_runtime_field": {
"type": "keyword",
"script": {
"source": "def m = /(.*)-bar-([0-9][0-9])/.matcher(doc['tokenstring3'].value); emit(m.find() ? m.group(1) + '_' + m.group(2) : '');"
}
}
}
}
GET _ml/datafeeds/datafeed-test2/_preview
- 此脚本查找特定的正则表达式模式,并将匹配的组作为连接的字符串发出。如果未找到匹配项,则发出一个空字符串。
预览数据源 API 返回以下结果,这些结果表明 "foo-bar-19" 已被转换为 "foo_19"
[
{
"@timestamp": 1490274000000,
"my_script_field": "foo_19"
}
]
PUT _ml/anomaly_detectors/test3
{
"analysis_config":{
"bucket_span": "10m",
"detectors":[
{
"function":"lat_long",
"field_name": "my_coordinates"
}
]
},
"data_description": {
"time_field":"@timestamp"
},
"datafeed_config":{
"datafeed_id": "datafeed-test3",
"indices": ["my-index-000001"],
"runtime_mappings": {
"my_coordinates": {
"type": "keyword",
"script": {
"source": "emit(doc['coords.lat'].value + ',' + doc['coords.lon'].value)"
}
}
}
}
}
GET _ml/datafeeds/datafeed-test3/_preview
在 Elasticsearch 中,位置数据可以存储在 geo_point
字段中,但机器学习分析本身不支持这种数据类型。此运行时字段示例将数据转换为适当的格式。有关更多信息,请参阅 地理函数。
预览数据源 API 返回以下结果,这些结果表明 41.44
和 90.5
已被组合成 "41.44,90.5"
[
{
"@timestamp": 1490274000000,
"my_coordinates": "41.44,90.5"
}
]