UpdateRecord

文档中心 › 组件索引 › UpdateRecord

UpdateRecord Processor

类型全限定名:cn.org.acal.lynxus.processors.standard.UpdateRecord

所属 Bundle:cn.org.acal.lynxus:lynxus-standard-nar:2.11.8

描述

更新包含面向记录数据的 FlowFile 的内容(即可以通过 RecordReader 读取并由 RecordWriter 写入的数据)。

标签

updaterecordgenericschemajsoncsvavrologlogsfreeformtext

使用场景

将多个字段合并为单个字段。

combineconcatenaterecordpath
"Replacement Value Strategy" = "Record Path Value"

向处理器添加一个额外的属性。该属性的名称是一个 RecordPath,用于标识放置结果的字段。
该属性的值使用 concat Record Path 函数将多个值连接在一起,可能会使用其他字符串字面值。
例如,要将 `title`、`firstName` 和 `lastName` 字段合并为名为 `fullName` 的单个字段,我们添加一个名为 `/fullName`、 值为 `concat(/title, ' ', /firstName, ' ', /lastName)` 的属性

将记录字段的值更改为显式值。

changeupdatereplacetransform
    "Replacement Value Strategy" = "Literal Value"

    向处理器添加一个额外的属性。该属性的名称是一个 RecordPath,用于标识放置结果的字段。
    该属性的值是要将该字段设置为的显式值。例如,无论字段 `txId` 在数据层次结构中的层级如何,     我们都可以通过添加一个名为 `//txId`、值为 `1111-1111` 的属性,将其设置为 `1111-1111`

将一个记录字段的值复制到另一个记录字段。

changeupdatecopyrecordpathhierarchytransform
    "Replacement Value Strategy" = "Record Path Value"

    向处理器添加一个额外的属性。该属性的名称是一个 RecordPath,用于标识要更新的字段。
    该属性的值是一个 RecordPath,用于标识从中复制值的字段。
    例如,我们可以将 `/identifiers/all/imei` 的值复制到根级别的 `identifier` 字段,方法是添加一个名为     `/identifier`、值为 `/identifiers/all/imei` 的属性。

通过将属性值注入每条记录来丰富数据。

enrichattributechangeupdatereplaceinserttransform
"Replacement Value Strategy" = "Literal Value"

向处理器添加一个额外的属性。该属性的名称是一个 RecordPath,用于标识放置结果的字段。
该属性的值是一个引用感兴趣属性的 Expression Language 表达式。例如,我们可以通过添加一个名为 `/filename`、 值为 `${filename}` 的属性,向每条记录插入一个新字段名 `filename`

更改记录字段值的格式。

说明:使用 RenameRecordField 处理器来更改字段的名称。

changeupdatereplaceinserttransformformatdate/timetimezoneexpression language
"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:
RecordReaderFactory
cn.org.acal.lynxus-lynxus-standard-services-api-nar-2.11.8
指定用于读取传入数据的 Controller Service
Record Writer控制器服务 API:
RecordSetWriterFactory
cn.org.acal.lynxus-lynxus-standard-services-api-nar-2.11.8
指定用于写出记录的 Controller Service
Replacement Value Strategyliteral-value
  • 字面值 — 为属性输入的值(在表达式语言求值后)就是用于更新记录字段的期望值。表达式语言可以引用变量 'field.name'、'field.type' 和 'field.value' 来访问有关字段和正在求值的字段值的信息。
  • 记录路径值 — 为属性输入的值(在表达式语言求值后)不是要使用的字面值,而是一个记录路径,应针对记录进行求值,记录路径的结果将用于更新记录。请注意,如果选择此选项,且记录路径对给定记录产生多个值,则输入 FlowFile 将被路由到 'failure' 关系。
指定如何解释配置的替换值

动态属性

动态属性允许用户自定义属性的名称与值。

名称值描述
一个 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": []
  }
]