UpdateRecord Processor
描述
更新包含面向记录数据的 FlowFile 的内容(即可以通过 RecordReader 读取并由 RecordWriter 写入的数据)。
标签
使用场景
将多个字段合并为单个字段。
"Replacement Value Strategy" = "Record Path Value"
向处理器添加一个额外的属性。该属性的名称是一个 RecordPath,用于标识放置结果的字段。
该属性的值使用 concat Record Path 函数将多个值连接在一起,可能会使用其他字符串字面值。
例如,要将 `title`、`firstName` 和 `lastName` 字段合并为名为 `fullName` 的单个字段,我们添加一个名为 `/fullName`、 值为 `concat(/title, ' ', /firstName, ' ', /lastName)` 的属性
将记录字段的值更改为显式值。
"Replacement Value Strategy" = "Literal Value"
向处理器添加一个额外的属性。该属性的名称是一个 RecordPath,用于标识放置结果的字段。
该属性的值是要将该字段设置为的显式值。例如,无论字段 `txId` 在数据层次结构中的层级如何, 我们都可以通过添加一个名为 `//txId`、值为 `1111-1111` 的属性,将其设置为 `1111-1111`
将一个记录字段的值复制到另一个记录字段。
"Replacement Value Strategy" = "Record Path Value"
向处理器添加一个额外的属性。该属性的名称是一个 RecordPath,用于标识要更新的字段。
该属性的值是一个 RecordPath,用于标识从中复制值的字段。
例如,我们可以将 `/identifiers/all/imei` 的值复制到根级别的 `identifier` 字段,方法是添加一个名为 `/identifier`、值为 `/identifiers/all/imei` 的属性。
通过将属性值注入每条记录来丰富数据。
"Replacement Value Strategy" = "Literal Value"
向处理器添加一个额外的属性。该属性的名称是一个 RecordPath,用于标识放置结果的字段。
该属性的值是一个引用感兴趣属性的 Expression Language 表达式。例如,我们可以通过添加一个名为 `/filename`、 值为 `${filename}` 的属性,向每条记录插入一个新字段名 `filename`
更改记录字段值的格式。
"Replacement Value Strategy" = "Literal Value"
向处理器添加一个额外的属性。该属性的名称是一个 RecordPath,用于标识要更新的字段。
该值是一个引用 `field.value` 变量的 Expression Language 表达式。例如,要将名为 `txDate` 的字段的日期/时间格式 从 `year-month-day` 格式更改为 `month/day/year` 格式,我们添加一个名为 `/txDate`、值为 `${field.value:toDate('yyyy-MM-dd'):format('MM/dd/yyyy')}` 的属性。我们还可以通过使用值为 `${field.value:toDate('yyyy-MM-dd HH:mm:ss', 'UTC-0400'):format('yyyy-MM-dd HH:mm:ss Z', 'UTC')}` 来更改时间戳字段的时区(并插入时区以求清晰)。
属性
| 名称 | 默认值 | 可选值 | 描述 |
|---|---|---|---|
| Record Reader | | 控制器服务 API:RecordReaderFactorycn.org.acal.lynxus-lynxus-standard-services-api-nar-2.11.8 | 指定用于读取传入数据的 Controller Service |
| Record Writer | | 控制器服务 API:RecordSetWriterFactorycn.org.acal.lynxus-lynxus-standard-services-api-nar-2.11.8 | 指定用于写出记录的 Controller Service |
| Replacement Value Strategy | literal-value |
| 指定如何解释配置的替换值 |
动态属性
| 名称 | 值 | 描述 |
|---|---|---|
| 一个 RecordPath。 | 用于替换记录中与 RecordPath 匹配的字段的值 | 允许用户指定用于替换匹配 RecordPath 的记录中字段的值。 |
关系 (Relationships)
| 名称 | 描述 | 自动终止 |
|---|---|---|
failure | 如果 FlowFile 无法从配置的输入格式转换为配置的输出格式,未更改的 FlowFile 将被路由到此关系 | 否 |
success | 成功转换的FlowFiles将被路由到此关系 | 否 |
写入的 FlowFile 属性
| 名称 | 描述 |
|---|---|
record.index | 此属性提供当前行索引,并且仅在文字值表达式内可用。 |
record.error.message | 此属性在失败时提供读取器或写入器遇到的错误消息。 |
状态管理
该组件不存储状态。
受限 (Restricted)
该组件不受限。
输入要求
该组件要求有传入连接。
另请参阅
详细说明
UpdateRecord
UpdateRecord 利用 Lynxus RecordPath 领域专用语言(DSL),让用户指定 Record 中应更新哪些字段。 做法是在 Processor 配置中添加用户自定义属性:属性名必须是要对每条记录求值的 RecordPath 文本,属性值则指定所选记录字段应填入什么值。
指定替换值(即用户自定义属性的值)时,用户可以指定字面量(例如数字 10)、用于引用
FlowFile Attribute 的表达式语言表达式(例如 ${filename}),或者另一个用于从记录本身
取值的 RecordPath 路径。输入的值应被解释为字面量还是 RecordPath 路径,由
如果给定的 RecordPath 不匹配输入记录中的任何字段,该属性会被跳过,其余属性仍会正常求值。
如果 RecordPath 恰好匹配一个字段,该字段会被更新为对应的值。如果多个字段匹配该
RecordPath,所有匹配的字段都会被更新。如果替换值本身是一个不匹配的 RecordPath,
字段会被设置为 null。如果这不是期望的行为,可以使用 RecordPath 谓词(predicate)
过滤匹配的字段,使任何字段都不会被选中。更多信息请参阅 RecordPath Predicates。
下面给出一些示例,以便更清楚地说明该 Processor 的行为。以下所有示例都基于下面这组 2 条(JSON)记录:
[
{
"id": 17,
"name": "John",
"child": {
"id": "1"
},
"siblingIds": [
4,
8
],
"siblings": [
{
"name": "Jeremy",
"id": 4
},
{
"name": "Julia",
"id": 8
}
]
},
{
"id": 98,
"name": "Jane",
"child": {
"id": 2
},
"gender": "F",
"siblingIds": [],
"siblings": []
}
]
为简洁起见,我们省略了对应的 schema 以及 RecordReader 和 RecordWriter 的配置。 以下考察为 Processor 配置了不同属性集合时的相应输出。
示例 1 - 用字面量替换
这里我们把每条记录的 name 替换为 'Jeremy',并把 gender 设为 'M':
| 属性名 | 属性值 |
|---|---|
| Replacement Value Strategy | Literal Value |
| /name | Jeremy |
| /gender | M |
输出如下:
[
{
"id": 17,
"name": "Jeremy",
"child": {
"id": "1"
},
"gender": "M",
"siblingIds": [
4,
8
],
"siblings": [
{
"name": "Jeremy",
"id": 4
},
{
"name": "Julia",
"id": 8
}
]
},
{
"id": 98,
"name": "Jeremy",
"child": {
"id": 2
},
"gender": "M",
"siblingIds": [],
"siblings": []
}
]
注意,尽管第一条记录在输入中没有 "gender" 字段,更新后仍会在 "child" 字段之后添加 该字段,因为在 schema 中该字段就位于那里。
示例 2 - 用 RecordPath 替换
此示例用记录中另一个字段的值替换某个字段的值。考虑以下属性集合:
| 属性名 | 属性值 |
|---|---|
| Replacement Value Strategy | Record Path Value |
| /name | /siblings[0]/name |
输出如下:
[
{
"id": 17,
"name": "Jeremy",
"child": {
"id": "1"
},
"siblingIds": [
4,
8
],
"siblings": [
{
"name": "Jeremy",
"id": 4
},
{
"name": "Julia",
"id": 8
}
]
},
{
"id": 98,
"name": null,
"child": {
"id": 2
},
"gender": "F",
"siblingIds": [],
"siblings": []
}
]
示例 3 - 用相对 RecordPath 替换
在上面的示例中,我们基于另一个 RecordPath 替换了字段的值。那个 RecordPath 是"绝对
RecordPath",即以"斜杠"字符(/)开头,因此指定的是从"根"(即最外层元素)开始的路径。
但有时我们希望以相对于被更新字段的方式来定义 RecordPath。本示例正是如此:对于
"siblings" 数组中的每个 sibling,我们把该 sibling 的 name 替换为其 id。为此,
给 Processor 配置以下属性:
| 属性名 | 属性值 |
|---|---|
| Replacement Value Strategy | Record Path Value |
| /siblings[*]/name | ../id |
注意,作为值给出的 RecordPath 以 .. 开头,这是对父级的引用。之所以这样做,是因为
我们要更新的字段是 sibling 的 "name" 字段。要获取对应的 "id" 字段,需要先回到
"name" 字段的父级,再进入其 "id" 子字段。上述示例的输出为:
[
{
"id": 17,
"name": "Jeremy",
"child": {
"id": "1"
},
"siblingIds": [
4,
8
],
"siblings": [
{
"name": "Jeremy",
"id": 4
},
{
"name": "Julia",
"id": 8
}
]
},
{
"id": 98,
"name": null,
"child": {
"id": 2
},
"gender": "F",
"siblingIds": [],
"siblings": []
}
]
示例 4 - 替换多个值
此示例替换所有名为 "id" 的字段的值,无论该字段位于记录层次结构的哪个位置。它使用的 值引用了表达式语言,因此本示例假设传入 FlowFile 有一个名为 "replacement.id"、 值为 "91" 的 Attribute:
| 属性名 | 属性值 |
|---|---|
| Replacement Value Strategy | Literal Value |
| //id | ${replacement.id} |
输出如下:
[
{
"id": 91,
"name": "John",
"child": {
"id": "91"
},
"siblingIds": [
4,
8
],
"siblings": [
{
"name": "Jeremy",
"id": 91
},
{
"name": "Julia",
"id": 91
}
]
},
{
"id": 91,
"name": "Jane",
"child": {
"id": 91
},
"gender": "F",
"siblingIds": [],
"siblings": []
}
]
还值得注意的是,本例中有些 "id" 字段是 STRING 类型,另一些是 INT 类型。这没有关系, 因为 RecordReader 和 RecordWriter 应当为我们处理这些简单的类型转换。
示例 5 - 使用表达式语言修改值
此示例把所有 'name' 字段的值转换为大写,无论该字段位于记录层次结构的哪个位置。 做法是在表达式语言中引用 'field.value' 变量。也可以访问 field.name 变量和 field.type 变量。
| 属性名 | 属性值 |
|---|---|
| Replacement Value Strategy | Literal Value |
| //name | ${field.value:toUpper()} |
输出如下:
[
{
"id": 17,
"name": "JOHN",
"child": {
"id": "1"
},
"siblingIds": [
4,
8
],
"siblings": [
{
"name": "JEREMY",
"id": 4
},
{
"name": "JULIA",
"id": 8
}
]
},
{
"id": 98,
"name": "JANE",
"child": {
"id": 2
},
"gender": "F",
"siblingIds": [],
"siblings": []
}
]