映射运行时字段

编辑

您可以通过在映射定义下添加一个 runtime 部分并定义Painless 脚本来映射运行时字段。此脚本可以访问文档的整个上下文,包括通过 params._source 访问的原始 _source 和任何已映射的字段及其值。在查询时,脚本会运行并为查询所需的每个脚本化字段生成值。

例如,以下请求中的脚本会从 @timestamp 字段(定义为 date 类型)计算星期几。脚本基于 timestamp 的值计算星期几,并使用 emit 返回计算值。

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "runtime": {
            "day_of_week": {
                "type": "keyword",
                "script": {
                    "source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH))"
                }
            }
        },
        "properties": {
            "@timestamp": {
                "type": "date"
            }
        }
    },
)
print(resp)
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    runtime: {
      day_of_week: {
        type: "keyword",
        script: {
          source:
            "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH))",
        },
      },
    },
    properties: {
      "@timestamp": {
        type: "date",
      },
    },
  },
});
console.log(response);
PUT my-index-000001/
{
  "mappings": {
    "runtime": {
      "day_of_week": {
        "type": "keyword",
        "script": {
          "source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH))"
        }
      }
    },
    "properties": {
      "@timestamp": {"type": "date"}
    }
  }
}

runtime 部分可以是以下任何数据类型

  • boolean
  • composite
  • date
  • double
  • geo_point
  • ip
  • keyword
  • long
  • lookup

类型为 date 的运行时字段可以接受 format 参数,与 date 字段类型完全相同。

类型为 lookup 的运行时字段允许从相关索引检索字段。请参阅 从相关索引检索字段

如果启用了 动态字段映射,其中 dynamic 参数设置为 runtime,则新字段会自动作为运行时字段添加到索引映射中。

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "dynamic": "runtime",
        "properties": {
            "@timestamp": {
                "type": "date"
            }
        }
    },
)
print(resp)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      dynamic: 'runtime',
      properties: {
        "@timestamp": {
          type: 'date'
        }
      }
    }
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    dynamic: "runtime",
    properties: {
      "@timestamp": {
        type: "date",
      },
    },
  },
});
console.log(response);
PUT my-index-000001
{
  "mappings": {
    "dynamic": "runtime",
    "properties": {
      "@timestamp": {
        "type": "date"
      }
    }
  }
}

定义没有脚本的运行时字段

编辑

运行时字段通常包含一个 Painless 脚本,该脚本以某种方式操作数据。但是,在某些情况下,您可能会定义一个没有脚本的运行时字段。例如,如果您想从 _source 中检索单个字段而不进行更改,则不需要脚本。您可以创建一个没有脚本的运行时字段,例如 day_of_week

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "runtime": {
            "day_of_week": {
                "type": "keyword"
            }
        }
    },
)
print(resp)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      runtime: {
        day_of_week: {
          type: 'keyword'
        }
      }
    }
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    runtime: {
      day_of_week: {
        type: "keyword",
      },
    },
  },
});
console.log(response);
PUT my-index-000001/
{
  "mappings": {
    "runtime": {
      "day_of_week": {
        "type": "keyword"
      }
    }
  }
}

当没有提供脚本时,Elasticsearch 会在查询时隐式地在 _source 中查找与运行时字段同名的字段,如果存在则返回一个值。如果不存在同名字段,则响应中不包含该运行时字段的任何值。

在大多数情况下,应尽可能通过 doc_values 检索字段值。使用运行时字段访问 doc_values 比从 _source 检索值更快,因为数据是从 Lucene 加载的。

但是,在某些情况下,必须从 _source 检索字段。例如,text 字段默认情况下没有可用的 doc_values,因此您必须从 _source 检索值。在其他情况下,您可能会选择禁用特定字段上的 doc_values

您也可以在要检索值的字段前加上 params._source 前缀(例如 params._source.day_of_week)。为了简单起见,建议尽可能在映射定义中定义没有脚本的运行时字段。

忽略运行时字段上的脚本错误

编辑

脚本可以在运行时抛出错误,例如,在访问文档中缺失或无效的值时,或者由于执行无效操作。 on_script_error 参数可用于控制发生这种情况时的错误行为。将此参数设置为 continue 将会静默忽略此运行时字段上的所有错误。默认值 fail 将导致分片失败,并在搜索响应中报告。

更新和删除运行时字段

编辑

您可以随时更新或删除运行时字段。要替换现有的运行时字段,请向映射添加一个具有相同名称的新运行时字段。要从映射中删除运行时字段,请将运行时字段的值设置为 null

resp = client.indices.put_mapping(
    index="my-index-000001",
    runtime={
        "day_of_week": None
    },
)
print(resp)
response = client.indices.put_mapping(
  index: 'my-index-000001',
  body: {
    runtime: {
      day_of_week: nil
    }
  }
)
puts response
const response = await client.indices.putMapping({
  index: "my-index-000001",
  runtime: {
    day_of_week: null,
  },
});
console.log(response);
PUT my-index-000001/_mapping
{
 "runtime": {
   "day_of_week": null
 }
}