在 Elasticsearch 中,在搜索请求中定义运行时字段(Runtime Fields)是一种强大的功能,允许用户在查询时动态添加和计算字段,而无需预先在索引映射中定义这些字段。这种方式提供了极大的灵活性,尤其是在处理动态数据结构或需要临时计算字段值的场景中。
运行时字段的核心概念
运行时字段基于“读时模式(Schema on Read)”的概念,允许用户在查询时定义字段的映射和计算逻辑。与传统的索引字段不同,运行时字段不会被存储或索引,因此不会增加存储成本。它们仅在查询执行时动态计算,并可用于查询、聚合和排序。
在搜索请求中定义运行时字段
运行时字段可以通过在搜索请求中添加`runtime_mappings`部分来定义。其语法与在索引映射中定义运行时字段的语法相同。例如:
```json
GET my-index-000001/_search
{
"runtime_mappings": {
"day_of_week": {
"type": "keyword",
"script": {
"source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH))"
}
}
},
"query": {
"match_all": {}
},
"aggs": {
"day_of_week_terms": {
"terms": {
"field": "day_of_week"
}
}
}
}
```
在这个例子中:
1. `runtime_mappings`部分定义了一个名为`day_of_week`的运行时字段,其类型为`keyword`。
2. 使用 Painless 脚本从`@timestamp`字段计算出一周中的某一天(如“Monday”)。
3. 该字段可以用于查询、聚合或排序。
运行时字段的优势
1. 动态性:运行时字段允许在查询时动态计算字段值,无需预先索引。
2. 节省存储空间:由于运行时字段不会被存储或索引,因此不会增加索引的存储成本。
3. 灵活性:运行时字段可以覆盖索引映射中已有的字段,或者添加新的字段,而无需修改索引结构。
4. 查询功能:运行时字段支持几乎所有的查询功能,包括聚合、过滤和排序。
使用场景
运行时字段适用于以下场景:
1. 动态数据结构:当数据结构不固定或需要动态解析字段时。
2. 临时字段:当需要临时计算字段值而不存储这些值时。
3. 纠正索引映射错误:如果字段被错误地映射为不适合的类型(如将数值字段映射为`text`),运行时字段可以覆盖这些字段的类型。
运行时字段的限制
尽管运行时字段提供了极大的灵活性,但它们也有一些限制:
1. 性能影响:由于运行时字段是在查询时动态计算的,因此可能会对查询性能产生一定影响。
2. 不可用于`_source`:运行时字段不会出现在`_source`中,只能通过`fields`参数返回。
示例:使用运行时字段进行聚合
假设您需要对某个字段进行聚合,但该字段未被索引为合适的类型,您可以使用运行时字段来解决这个问题。例如:
```json
PUT my-index-000001/_mapping
{
"runtime": {
"measures.start": {
"type": "long"
}
}
}
GET my-index-000001/_search
{
"aggs": {
"avg_start": {
"avg": {
"field": "measures.start"
}
}
}
}
```
在这个例子中,运行时字段`measures.start`被定义为`long`类型,从而可以对其进行聚合。
总结
运行时字段是 Elasticsearch 中一种强大的功能,允许用户在查询时动态定义和计算字段值。它们提供了灵活性和动态性,同时节省了存储空间。然而,运行时字段可能会对查询性能产生一定影响,因此需要根据具体场景进行权衡。