Java pig拉丁语中展平算子的模式

Java pig拉丁语中展平算子的模式,java,apache-pig,Java,Apache Pig,我最近在工作中遇到了这个问题,是关于猪压扁的。我用一个简单的例子来表达它 两个文件 ===文件1=== 1_a 2_b 四 ==文件2(制表符分开)== 1A 2b 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:char

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

两个文件
===文件1===
1_a
2_b

==文件2(制表符分开)==
1A
2b
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
|---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: (*))

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

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

还要注意,在file1中,您使用下划线作为分隔符,但将“-”作为STRSPLIT的参数

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

至于问题的根源,我将大胆猜测,可能与此()以及pig的运行周期优化有关:

如果将内部模式为空的包展平,则结果关系的模式为空

在您的例子中,我相信STRSPLIT结果的模式在运行时之前是未知的

edit2: 好的,下面是我的理论解释:

和。我会把有趣的部分贴在这里

|---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;请看最后一行。它假定
flatte(STRSPLIT)
的输出将具有类型为
integer
的第一个元素(因为您以这种方式提供了模式)。但实际上,
STRSPLIT
有一个
null
输出模式,它被视为
bytearray
字段;所以,展平(STRSPLIT)的输出实际上是
(n:bytearray,c:bytearray)
。因为您提供了一个模式,pig尝试将java强制转换(到
a1
的输出)到
num
字段;由于
num
而失败的字符串实际上是一个用bytearray表示的java
字符串。由于这个java转换失败,pig甚至不尝试在上面的行中进行显式转换

让我们看看脚本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
|---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尝试(并成功)进行显式强制转换操作,从
bytearray
integer

是的,我在开始时使用了PigStorage,但在这个过程中生成了像“\u0”这样的数据格式,所以我别无选择,只能使用strSplite,因为“-”是我的疏忽,实际上代码是正确的,谢谢您的回答。但我仍然不明白,当你描述a1时,Pig给出了a1:{num:int,ch:chararray},为什么这个模式不能用在连接操作符中。还有script2和script3之间的区别,一个命名为Field,另一个命名为Not。因此您的意思是强制转换异常发生在**AS子句**中,但是
dump a1
没有导致异常cast异常是由AS子句引起的。尽管在调用dump或store之前不会对其(AS子句)求值。