3

我最近在工作中遇到了这个问题,它是关于猪扁平化的。我用一个简单的例子来表达

两个文件
===file1===
1_a
2_b
4_d

===file2(制表符分隔)===
1 a
2 b
3 c

猪脚本1:

a = load 'file1' as (str:chararray);
b = load 'file2' as (num:int, ch:chararray);
a1 = foreach a generate flatten(STRSPLIT(str,'_',2)) as (num:int, ch:chararray);
c = join a1 by num, b by num;
dump c;   -- exception java.lang.String cannot be cast to java.lang.Integer

猪脚本2:

a = load 'file1' as (str:chararray);
b = load 'file2' as (num:int, ch:chararray);
a1 = foreach a generate flatten(STRSPLIT(str,'_',2)) as (num:int, ch:chararray);
a2 = foreach a1 generate (int)num as num, ch as ch;
c = join a2 by num, b by num;
dump c;   -- exception java.lang.String cannot be cast to java.lang.Integer

猪脚本3:

a = load 'file1' as (str:chararray);
b = load 'file2' as (num:int, ch:chararray);
a1 = foreach a generate flatten(STRSPLIT(str,'_',2));
a2 = foreach a1 generate (int)$0 as num, $1 as ch;
c = join a2 by num, b by num;
dump c;   -- right

我不知道为什么脚本 1,2 是错误的而脚本 3 是正确的,我也想知道是否有更简洁的表达式来获得关系 c,谢谢。

4

1 回答 1

4

您没有使用 PigStorage 有什么特别的原因吗?因为它可以让你的生活变得更轻松:)。

a = load '/file1' USING PigStorage('_') AS (num:int, char:chararray);
b = load '/file2' USING PigStorage('\t') AS (num:int, char:chararray);
c = join a by num, b by num;
dump c;

另请注意,在 file1 中,您使用下划线作为分隔符,但您将“-”作为参数提供给 STRSPLIT。

编辑: 我在您提供的脚本上花了更多时间;脚本 1 和 2 确实不起作用,脚本 3 也可以这样工作(没有额外的 foreach):

a = load 'file1' as (str:chararry);
b = load 'file2' as (num:int, ch:chararry);
a1 = foreach a generate flatten(STRSPLIT(str,'_',2));
c = join a1 by (int)($0), b by num;
dump c;

至于问题的根源,我会大胆猜测并说它可能与此相关(如 Pig 文档中所述)以及 pig 的运行周期优化:

如果你 FLATTEN 一个内部模式为空的包,则结果关系的模式为空。

在您的情况下,我相信 STRSPLIT 结果的模式在运行之前是未知的。

edit2: 好的,这是我的理论解释:

这是脚本 2 的完整 -explain- 输出这是针对脚本 3 的。我将在这里粘贴有趣的部分。

|---a2: (Name: LOForEach Schema: num#288:int,ch#289:chararray)
|   |   |
|   |   (Name: LOGenerate[false,false] Schema: num#288:int,ch#289:chararray)ColumnPrune:InputUids=[288, 289]ColumnPrune:OutputUids=[288, 289]
|   |   |   |
|   |   |   (Name: Cast Type: int Uid: 288)
|   |   |   |
|   |   |   |---num:(Name: Project Type: int Uid: 288 Input: 0 Column: (*))

以上部分适用于脚本 2;见最后一行。它假设输出flatten(STRSPLIT)将具有类型的第一个元素integer(因为您以这种方式提供了架构)。但实际上STRSPLIT有一个null输出模式,它被视为bytearray字段;所以输出flatten(STRSPLIT)实际上是(n:bytearray, c:bytearray)。因为您提供了一个模式,所以 pig 尝试将 java 强制转换(到 的输出a1)到num字段;它失败了,因为num实际上是一个String表示为 bytearray 的 java。由于这个 java-cast 失败,pig 甚至不会尝试在上面的行中进行显式转换。

让我们看看脚本 3 的情况:

|---a2: (Name: LOForEach Schema: num#85:int,ch#87:bytearray)
|   |   |
|   |   (Name: LOGenerate[false,false] Schema: num#85:int,ch#87:bytearray)ColumnPrune:InputUids=[]ColumnPrune:OutputUids=[85, 87]
|   |   |   |
|   |   |   (Name: Cast Type: int Uid: 85)
|   |   |   |
|   |   |   |---(Name: Project Type: bytearray Uid: 85 Input: 0 Column: (*))

看最后一行,这里的输出a1被正确处理为bytearray,这里没有问题。现在看看倒数第二行;pig 尝试(并成功)从 to 进行显式bytearray转换操作integer

于 2012-09-03T06:11:32.590 回答