本篇是第 3 章第 3 节,是转换的心脏,盘点最常被拖进图里的加工步骤,决定数据质量。
「字段选择」是出场率最高的步骤:改名、改类型、裁剪列、调整顺序。我们几乎每个转换都以它打头,先把上游杂乱的字段规整成统一契约,后面步骤都基于稳定结构工作,减少连锁改动。
「过滤行」按条件分流,合法走真跳、非法走假跳,是脏数据隔离的第一道闸。我们把它和「写日志」或「错误表输出」配合,让问题数据可追溯而非默默丢弃。这一点在金融场景尤为重要,丢数等于事故。
「值映射」把状态码翻成中文或统一枚举,比如 0/1 翻成 否/是。但要注意映射表不全时会把未知值原样放过,我们习惯在后面接一个「校验」步骤兜未知值,双保险。
字符串加工用「替换字符串」「拆分字段」「合并字段」;数值用「计算器」做四则和取整。复杂到这些步骤拼不出时,我们用「JavaScript 代码」步骤写一小段脚本,但会严格控制其体量,避免把转换变成代码堆。
还有「去重」「排序」「分组」这类阻塞步骤,需要攒数据。我们只在确需全局有序时才用排序,能用「数据库查询」在库端排好就不在 Kettle 内排。阻塞步骤是性能的拐点,第三章一直强调后置与控量。
下面这段 xml 给出了可直接落地的配置,输入来自上一步、输出写入目标端:
<step><name>字段选择</name><type>SelectValues</type> <fields> <field><name>user_id</name><rename>uid</rename></field> <field><name>amount</name><type>Number</type><length>18</length><precision>2</precision></field> <field><name>remark</name><remove>Y</remove></field> </fields> </step>
改名、定点、删冗余三件事一步完成,是转换起手式。我们规定每个转换前两段固定是「字段选择」+「过滤」,形成团队可读的视觉习惯。
// JavaScript 步骤:只有简单逻辑才落在这里 var full_name = trim(first_name) + ' ' + trim(last_name); if (age == null || age < 0) { age = 0; // 异常年龄归零,下游再标记 } var age_band = (age < 18) ? '未成年' : (age < 60 ? '成年' : '老年');
脚本只处理步骤拼不出的逻辑。我们禁止在 JavaScript 里写大段业务,那会丧失可视化的可维护性优势。
<step><name>值映射</name><type>ValueMapper</type> <field_from>status</field_from> <field_to>status_cn</field_to> <mappings><map><value_from>1</value_from><value_to>已支付</value_to></map></mappings> </step>
状态翻译用值映射比脚本更可读。我们维护一份共享映射片段,多个转换复用,避免各处翻译不一致。
订单表混入了测试账号的脏记录,直接进汇总会拉偏指标,但业务方又要求保留可追溯。
在转换中加「过滤行」:测试标记为真则走假跳写错误表,正常走真跳继续。
<step><name>过滤</name><type>FilterRows</type> <field>is_test</field><condition><>[is not equal to]Y</condition></step>
脏数据进错误表供审计,主链路指标恢复准确,且没丢任何原始记录。
根因是缺少分流闸口。转换步骤的价值不仅在「洗」,更在「分」——把不同质量的数据路由到不同归宿,这正是图形化的强项。
若脏规则很多,可把过滤条件抽到「JavaScript」统一判断并打标,再按标签分流,规则集中更好维护。
误区:所有加工塞进 JavaScript。优先用原生步骤,脚本只补死角。
误区:映射不全就放行。未知值要接校验步骤兜底。
取舍:阻塞步骤能下推库端就下推,Kettle 内只做必要加工。

字段选择(SelectValues)做改名、裁剪、类型转换,是治理入口;值映射(ValueMapper)把状态码翻成中文等枚举;过滤(Filter)按条件分流到两个分支;计算器(Calculator)做行间算术;JavaScript 步骤处理无法用现成步骤表达的复杂逻辑,但要警惕它把「本可下推的运算」拖进内存。排序/分组/去重是阻塞式,前文强调过它们会等全量到齐。选步骤的第一原则:能用数据库 SQL 下推的,别在内存里用步骤算。
// JavaScript 步骤示例:把金额按汇率折算并打标签(输入:行集 amount/status;输出:行集 amt_cny/is_paid) var amt_cny = amount * rate; // rate 由「获取变量」步骤注入 var is_paid = (status == 1) ? "Y" : "N"; // 状态 1 视为已支付 trans_Status = SKIP_TRANSFORMATION; // 仅输出新增字段,原字段透传
| 步骤 | 用途 | 是否阻塞 |
|---|---|---|
| 字段选择 | 改名/裁剪/转型 | 否 |
| 值映射 | 枚举翻译 | 否 |
| 过滤 | 条件分流 | 否 |
| 排序/分组 | 聚合前处理 | 是 |