Elasticsearch:Runtime fields - 运行时字段(一)

news2025/1/11 18:41:12

运行时字段(runtime fields)是在查询时计算的字段。运行时字段使你能够:

  • 向现有文档添加字段而无需重新索引数据
  • 开始处理数据而无需了解其结构
  • 在查询时覆盖索引字段返回的值
  • 定义用于特定用途的字段而无需修改底层架构

你可以像访问其他任何字段一样从 search API 访问运行时字段,Elasticsearch 对运行时字段的看法也一样。你可以在 index mapping 或 search request 中定义运行时字段。你的选择是运行时字段固有灵活性的一部分。

使用 _search API 上的 fields 参数来检索运行时字段的值。运行时字段不会显示在 _source 中,但 fields API 适用于所有字段,即使是那些未作为原始 _source 的一部分发送的字段。

运行时字段在处理日志数据时很有用(参见后面的示例),尤其是当你不确定数据结构时。你的搜索速度会降低,但索引大小会小得多,你可以更快地处理日志而无需索引它们。

使用运行时字段带来的好处

由于运行时字段未编入索引,因此添加运行时字段不会增加索引大小。你可以直接在索引映射中定义运行时字段,从而节省存储成本并提高提取速度。你可以更快地将数据提取到 Elastic Stack 中并立即访问。定义运行时字段后,你可以立即将其用于搜索请求、聚合、过滤和排序。

如果将运行时字段更改为索引字段,则无需修改引用该运行时字段的任何查询。更好的是,你可以引用一些字段是运行时字段的索引,以及字段是索引字段(indexed field)的其他索引。你可以灵活地选择要索引哪些字段以及将哪些字段保留为运行时字段。

从本质上讲,运行时字段最重要的好处是能够在提取字段后将字段添加到文档中。此功能简化了映射决策,因为你不必预先决定如何解析数据,并且可以随时使用运行时字段来修改映射。使用运行时字段允许更小的索引和更快的摄取时间,从而结合使用更少的资源并降低运营成本。

激励

运行时字段可以取代使用 _search API 编写脚本的许多方式。运行时字段的使用方式受所包含脚本所针对的文档数量的影响。例如,如果你使用 _search API 上的 fields 参数来检索运行时字段的值,则脚本只会像脚本字段一样针对热门匹配项运行。

你可以使用脚本字段(script fields)访问 _source 中的值并返回基于脚本估值的计算值。运行时字段具有相同的功能,但提供了更大的灵活性,因为你可以在搜索请求中查询和聚合运行时字段。脚本字段只能获取值。

同样,你可以编写一个 script query,根据脚本过滤搜索请求中的文档。运行时字段提供了一个非常相似的功能,但更加灵活。你编写一个脚本来创建字段值,它们在任何地方都可用,例如 fields、所有查询和聚合。

你还可以使用脚本对搜索结果进行排序,但同一个脚本在运行时字段中的工作方式完全相同。

如果你将脚本从搜索请求中的任何部分移至从相同数量的文档计算值的运行时字段,则性能应该大致相同。这些功能的性能在很大程度上取决于所包含脚本正在运行的计算以及脚本针对多少个文档运行。

折衷

运行时字段占用较少的磁盘空间,并为你提供访问数据的灵活性,但可能会根据运行时脚本中定义的计算影响搜索性能。

为了平衡搜索性能和灵活性,请索引你经常搜索和过滤的字段,例如时间戳。Elasticsearch 在运行查询时会自动首先使用这些索引字段,从而缩短响应时间。然后,你可以使用运行时字段来限制 Elasticsearch 需要计算值的字段数量。将索引字段与运行时字段结合使用,可以灵活地索引数据以及如何定义其他字段的查询。

使用 asynchronous search API 运行包含运行时字段的搜索。这种搜索方法有助于抵消计算每个包含该字段的文档中的运行时字段值对性能的影响。如果查询无法同步返回结果集,你将在结果可用时异步获得结果。

重要:针对运行时字段的查询被认为是昂贵的。如果 search.allow_expensive_queries 设置为 false,则不允许昂贵的查询,并且 Elasticsearch 将拒绝任何针对运行时字段的查询。

映射运行时字段

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

发出运行时字段值

在定义用于运行时字段的 Painless 脚本时,必须包含 emit 方法来发出计算值。

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

PUT my-index-000001
{
  "mappings": {
    "runtime": {
      "day_of_week": {
        "type": "keyword",
        "script": {
          "source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
        }
      }
    },
    "properties": {
      "@timestamp": {"type": "date"}
    }
  }
}

PUT my-index-000001/_doc/1
{
  "@timestamp": "2024-06-24T04:54:59"
}

我们可以使用如下的命令来查看我们的索引:

GET my-index-000001/_search
{
  "fields": [
    "day_of_week"
  ]
}

上面的命令返回的结果为:

{
  "took": 19,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "my-index-000001",
        "_id": "1",
        "_score": 1,
        "_source": {
          "@timestamp": "2024-06-24T04:54:59"
        },
        "fields": {
          "day_of_week": [
            "Monday"
          ]
        }
      }
    ]
  }
}

在上面,我们可以看到 day_of_week 的字段值为 Monday。

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

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

具有日期类型的运行时字段可以接受与 date 字段类型完全相同的 format 参数。

具有 lookup 类型的运行时字段允许从相关索引中检索字段。请详细参阅之后的章节。如果启用了 dynamic field mapping,其中 dynamic 参数设置为 runtime,则新字段将自动作为运行时字段添加到索引映射中:

PUT my-index-000001
{
  "mappings": {
    "dynamic": "runtime",
    "properties": {
      "@timestamp": {
        "type": "date"
      }
    }
  }
}

定义运行时字段而不使用脚本

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

PUT my-index-000001/
{
  "mappings": {
    "runtime": {
      "day_of_week": {
        "type": "keyword"
      }
    }
  }
}

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

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

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

注意:你也可以在要检索值的字段前加上 params._source 前缀(例如 params._source.day_of_week)。为简单起见,建议尽可能在映射定义中定义运行时字段而不使用脚本。

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

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

更新和删除运行时字段

你可以随时更新或删除运行时字段。要替换现有运行时字段,请将新运行时字段添加到同名映射中。要从映射中删除运行时字段,请将运行时字段的值设置为 null:

PUT my-index-000001/_mapping
{
 "runtime": {
   "day_of_week": null
 }
}

下游影响 - Downstream impacts

在依赖查询运行时更新或删除运行时字段可能会返回不一致的结果。每个分片可能有权访问脚本的不同版本,具体取决于映射更改的生效时间。

警告:如果你删除或更新字段,则 Kibana 中依赖于运行时字段的现有查询或可视化可能会失败。例如,如果将类型更改为布尔值或删除运行时字段,则使用 ip 类型运行时字段的条形图可视化将会失败。

在搜索请求中定义运行时字段

你可以在搜索请求中指定一个 runtime_mappings 部分,以创建仅作为查询的一部分存在的运行时字段。你可以将脚本指定为 runtime_mappings 部分的一部分,就像将运行时字段添加到映射一样。

在搜索请求中定义运行时字段使用的格式与在索引映射中定义运行时字段的格式相同。只需将字段定义从索引映射中的运行时复制到搜索请求的 runtime_mappings 部分即可。

以下搜索请求将 day_of_week 字段添加到 runtime_mappings 部分。字段值将动态计算,并且仅在此搜索请求的上下文中计算:

DELETE my-index-000001

PUT my-index-000001/_doc/1
{
  "@timestamp": "2024-06-24T04:54:59"
}

GET my-index-000001/_search
{
  "runtime_mappings": {
    "day_of_week": {
      "type": "keyword",
      "script": {
        "source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
      }
    }
  },
  "aggs": {
    "day_of_week": {
      "terms": {
        "field": "day_of_week"
      }
    }
  }
}

上面查询请求的结果为:

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "my-index-000001",
        "_id": "1",
        "_score": 1,
        "_source": {
          "@timestamp": "2024-06-24T04:54:59"
        }
      }
    ]
  },
  "aggregations": {
    "day_of_week": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "Monday",
          "doc_count": 1
        }
      ]
    }
  }
}

创建使用其他运行时字段的运行时字段

你甚至可以在搜索请求中定义运行时字段,以返回来自其他运行时字段的值。例如,假设你批量索引一些传感器数据:

DELETE my-index-000001

POST my-index-000001/_bulk?refresh=true
{"index":{}}
{"@timestamp":1516729294000,"model_number":"QVKC92Q","measures":{"voltage":"5.2","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516642894000,"model_number":"QVKC92Q","measures":{"voltage":"5.8","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516556494000,"model_number":"QVKC92Q","measures":{"voltage":"5.1","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516470094000,"model_number":"QVKC92Q","measures":{"voltage":"5.6","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516383694000,"model_number":"HG537PU","measures":{"voltage":"4.2","start": "400","end":"8625309"}}
{"index":{}}
{"@timestamp":1516297294000,"model_number":"HG537PU","measures":{"voltage":"4.0","start": "400","end":"8625309"}}

索引后,你意识到你的数字数据被映射为 text 类型。你想在 measures.start 和 measures.end 字段上进行聚合,但聚合失败,因为你无法在文本类型的字段上进行聚合。运行时字段来拯救你!你可以添加与索引字段同名的运行时字段并修改数据类型:

PUT my-index-000001/_mapping
{
  "runtime": {
    "measures.start": {
      "type": "long"
    },
    "measures.end": {
      "type": "long"
    }
  }
}

运行时字段优先于索引映射中用相同名称定义的字段。这种灵活性允许你隐藏现有字段并计算不同的值,而无需修改字段本身。如果你在索引映射中犯了错误,则可以使用运行时字段来计算在搜索请求期间覆盖映射中的值的值。

现在,你可以轻松地对 measures.start 和 measures.end 字段运行平均聚合:

GET my-index-000001/_search
{
  "size": 0, 
  "aggs": {
    "avg_start": {
      "avg": {
        "field": "measures.start"
      }
    },
    "avg_end": {
      "avg": {
        "field": "measures.end"
      }
    }
  }
}

响应包括聚合结果,但不改变基础数据的值:

此外,你可以将运行时字段定义为计算值的搜索查询的一部分,然后在同一查询中对该字段运行统计聚合。

duration 运行时字段在索引映射中不存在,但我们仍然可以在该字段上进行搜索和聚合。以下查询返回持续时间字段的计算值,并运行统计聚合以计算从聚合文档中提取的数值的统计信息。

GET my-index-000001/_search
{
  "size": 0, 
  "runtime_mappings": {
    "duration": {
      "type": "long",
      "script": {
        "source": """
          emit(doc['measures.end'].value - doc['measures.start'].value);
          """
      }
    }
  },
  "aggs": {
    "duration_stats": {
      "stats": {
        "field": "duration"
      }
    }
  }
}

即使 duration 运行时字段仅存在于搜索查询的上下文中,你也可以搜索并聚合该字段。这种灵活性非常强大,使你能够在单个搜索请求中纠正索引映射中的错误并动态完成计算。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1886734.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

d3dcompiler_47.dll缺失怎么修复?d3dcompiler_47.dll修复使用说明

d3dcompiler_47.dll是一个重要的系统文件,属于MicrosoftWindows操作系统中Direct3D的一部分,它主要负责处理在Windows上运行的应用程序和游戏中的3D图形编程。这个DLL文件是“DirectX”的一项组成部分,DirectX是一套核心技术,用于…

【计算机网络仿真】b站湖科大教书匠思科Packet Tracer——实验13 静态路由配置错误导致的路由环路问题

一、实验目的 1.验证静态路由配置错误导致的路由环路问题; 二、实验要求 1.使用Cisco Packet Tracer仿真平台; 2.观看B站湖科大教书匠仿真实验视频,完成对应实验。 三、实验内容 1.构建网络拓扑; 2.验证路由环路。 四、实验…

嵌套组合请求对象的校验与全局捕捉

个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119qq.com] &#x1f4f1…

S7-1500PLC通过工艺对象实现V90总线伺服定位控制(105报文)

S7-1500PLC通过工艺对象实现V90总线伺服定位控制,伺服驱动器工作在速度模式,S7-1500PLC工作在位置模式,具体控制原理框图,可以参考下面文章链接: 1、S7-1200PLC和V90总线伺服位置控制 S7-1200PLC和V90总线伺服通过工艺对象实现定位控制(标准报文3应用)_v90伺服 报文3 设…

聊聊etsy平台,一个年入百万的项目

聊聊etsy平台,一个年入百万的项目 什么是etsy,这是怎样一个平台,怎样盈利的?相信现在大家满脑子都是这些疑问。 这个平台也是无意间一个学员提到的,据说他朋友靠这个平台年赚好几百万。苦于门槛太高,他也做不了。今天…

微软预计年底实现实时语音界面;硅基智能开源 AI 数字人交互平台 Duix丨 RTE 开发者日报

开发者朋友们大家好: 这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

基于matlab的控制系统串联校正—相位超前校正问题实例

1.问题 为了改进闭环系统性能,可以采用串联校正,这里用相位超前校正,即 α 常取 0.07~0.2 ,选择适当的 α 与 τ , 要使 针对新的开环传递函数 G ’ K (S)Gc(S) G(S) H(S) ,画出开环 Bode 图&#xff…

停车场车牌识别计费系统,用Python如何实现?

关注星标,每天学习Python新技能 前段时间练习过的一个小项目,今天再看看,记录一下~ 项目结构 说明: datefile文件夹:保存车辆信息表的xlsx文件 file文件夹:保存图片文件夹。ic_launcher.jpg是窗体的右上角…

Laravel swagger接口文档生成和管理

Laravel swagger接口文档生成和管理 接口开发随着时间推移接口会越来越多,随着多部门之间的协作越来越频繁, 维护成本越来越高, 文档的可维护性越来越差, 需要一个工具来管理这些接口的文档, 并能够充当mock server给调用方使用 这里推荐swagger生成和管理接口文档&…

Python入门 2024/7/2 While

目录 while循环的基础应用 循环输出十次:键盘敲烂,月入过万 计算1~100的和 用while循环练习猜数字 while循环的嵌套应用 打印九九乘法表 输出不换行的功能 while循环的基础应用 格式: while 条件: 条件满足时&#xff0c…

昇思25天学习打卡营第1天|yulang

今天主要了解了深度学习框架之昇思MindSpore的初学入门,没想到 ai学习入门如此简单,不愧是华为大手笔,提供的学习环境配置如此之高。这个平台有点类似百度飞桨,大大降低了AI开发门槛,使用户能够快速实现想要的模型&…

从零开始:如何设计一个现代化聊天系统

写在前面: 此博客内容已经同步到我的博客网站,如需要获得更优的阅读体验请前往https://mainjaylai.github.io/Blog/blog/system/chat-system 在当今数字化时代,聊天系统已成为我们日常生活和工作中不可或缺的一部分。从个人交流到团队协作,从客户服务到社交网络,聊天应用…

科技与水利的深度融合实践:揭秘智慧水利技术如何助力水利行业解决传统难题,推动水资源管理向精细化、智能化方向发展

本文关键词:智慧水利、智慧水利工程、智慧水利发展前景、智慧水利技术、智慧水利信息化系统、智慧水利解决方案、数字水利和智慧水利、数字水利工程、数字水利建设、数字水利概念、人水和协、智慧水库、智慧水库管理平台、智慧水库建设方案、智慧水库解决方案、智慧…

HR 如何用好人才测评系统?

HR 如何用好人才测评系统? 人才测评已经广泛应用在企业招聘、人才选拔,人才盘点,岗位晋升,绩效考评等领域,帮助HR提升人力资源管理效率,更好的发掘人才优势,在教育培训方面,人才测评…

我做了个C++算法学习网站,从语法到算法再到数据结构,全方位为算法竞赛小伙伴护航

哈喽,各位小伙伴大家好,我是大李。 最近半个月,我做了个《C算法宝典》并更新了40多篇教程,目前还在更新中,内容从语法到算法和数据结构,全方位为算法竞赛小伙伴护航。 温馨提示:如果你或你的朋…

prescan软件中导入路径文件txt/lpx

由于博主收到的是lpx格式的路径文件,因此,第一步 1.记事本打开 ctrla 全选 ctrlc 复制 2.新建一个excel 鼠标定位到第一行第一列的格子 ctrlv 复制 3.数据栏“分列”功能 4. (0.1递增的数列,纬度,经度,高程) 导入…

解决obsidian加粗字体显示不突出的问题

加粗字体显示不突出的原因:默认字体的加粗版本本来就不突出 解决方法:改成显示突出的类型Microsoft YaHei UI 【效果】 修改前:修改后: 其他方法: 修改css(很麻烦,改半天也不一定奏效&#…

中国民间网络外交组织(CCND)

中国民间网络外交组织Chinese Civil Network Diplomacy简称(CCDN) 是由中国网民建立起来的一个网络外交组织,深度贯彻党的主张和网民意志的统一,为保护中国中华优秀传统文化,民族自信,国家安全,民族利益,社…

pandas数据分析(4)

修改DataFrame数据的最简单的方法是通过loc和iloc属性为某些元素赋值。 首先构造一组数据 通过标签或位置设置值 也可以一次修改多个值: 通过布尔索引设置数据 将所有来自China,或者年龄20以下的人名字设置为匿名: 通过替换值设置数据 如果…

【讨论C++继承】

讨论C继承 继承定义继承方式和访问限定符 基类和派生类的赋值转换继承中的作用域派生类的默认成员函数继承和友元继承和静态成员菱形继承虚拟继承 继承是面向对象程序设计中,使代码可以复用的重要手段,它允许程序员在保持原有类特性的基础上进行扩展。 继…