替换 Pig 元组中字段的值

Posted

技术标签:

【中文标题】替换 Pig 元组中字段的值【英文标题】:Replace a value of a field in a tuple in Pig 【发布时间】:2013-05-30 15:45:09 【问题描述】:

我有两个数据集要加入。以下是它们的样子:

 Dataset 1
 ---#----#----#------------#----#-----#-----
 F1 | F2 | F3 | UID        | F4 | ... | F32
 ---#----#----#------------#----#-----#-----
 a1 | b1 | c1 | MD5 value1 | d1 | ... | foo1
 a2 | b2 | c2 | MD5 value2 | d2 | ... | foo2
 a3 | b3 | c3 | MD5 value3 | d3 | ... | foo3
 a4 | b4 | c4 | MD5 value4 | d4 | ... | foo4

 Dataset 2
 ----#-----#--------------#-----#-----#-----
 Z1  | Z2  | UID+Constant | Z3  | ... | Z62
 ----#-----#--------------#-----#-----#-----
 p1  | q1  | MD5 value1+C | s1  | ... | t1
 p2  | q2  | MD5 value2+C | s2  | ... | t2
 p3  | q3  | MD5 value3+C | s3  | ... | t3
 p4  | q4  | MD5 value4+C | s4  | ... | t4

现在我使用明确的字段名称来加载两个数据集:

D1 = LOAD '/dataset1' USING PigStorage(',')
     AS (F1:chararray, F2:chararray, F3:chararray, UID:chararray, ... , F32:chararray);

D2 = LOAD '/dataset2' USING PigStorage(',')
     AS (Z1:chararray, Z2:chararray, UID_C:chararray, ... , Z62:chararray);

现在,当我加入 UID 值时,我想从两个数据集中获取组合输出。因此,我使用REGEX_EXTRACT_ALLUID_C 字段拆分为D2。以下是我的做法。

D2_SPLIT_UID_C = FOREACH D2 GENERATE *,
                    FLATTEN(REGEX_EXTRACT_ALL(UID_C, '^(.*)\+(.*)$'))
                        AS (UID:chararray, C:chararray);

然后我在两个数据集上加入 UID

JOINED_DATA = JOIN D1 BY UID, D2_SPLIT_UID_C BY UID;

到目前为止一切顺利,但现在,我必须生成没有 UID_C 字段的输出。相反,我需要将其替换为 UID 的值。另外,我的最终输出中不需要Constant(C)

所以,我需要先从D1 生成数据,然后再从D2 生成数据。所以这是我最终输出的输出标题

---#----#----#------------#----#-----#-----#----#----#-----#----#-----#----
F1 | F2 | F3 | UID        | F4 | ... | F32 | Z1 | Z2 | UID | Z3 | ... | Z62
---#----#----#------------#----#-----#-----#----#----#-----#----#-----#----

这就是它变得丑陋的地方。我需要将 dataset1 和 dataset2 中的所有字段再次放入我的最终FOREACH GENERATE F1, F2, F3, UID, ...., F32, Z1, Z2, UID, Z3, ...., Z62。这样,如果明天我的架构发生变化,我也必须在这里更新它。

我不能用 UID 值替换 UID_C 列值,然后我只需要使用 FOREACH GENERATE * 就可以完成了吗?

【问题讨论】:

如果它是一个常量并且您只需要 MD5,那么您为什么要使用正则表达式而不是仅具有适当长度的 SUBSTRING 我们希望常量稍后用于不同的目的。 【参考方案1】:

您可以使用project-range 表达式来定义字段范围,例如: 跳过 UID_C 以及 MD5 和之后的常数:

D2_SPLIT_UID_C = FOREACH D2 GENERATE Z1 .. Z2, Z3 .. Z62, 
  FLATTEN(REGEX_EXTRACT(UID_C, '^(.*)\\+.*$', 1)) AS (UID:chararray);

【讨论】:

但仍然没有解决我的问题。实际上这些字段名称是虚拟的。所以,Z3 .. Z62 是不可能的。

以上是关于替换 Pig 元组中字段的值的主要内容,如果未能解决你的问题,请参考以下文章

用于连接元组中的值的 Pig 脚本

PIG 对元组中的对应元素求和

元组中的元素到 Bag Pig 中的元组

apache pig Java UDF - 更改属性中的值似乎并没有坚持

使用元组进行 Pig 编程

Pandas 替换列中的值,但 to_replace 参数是包含元组的元组