【问题标题】:schema of flatten operator in pig latin猪拉丁文中扁平化运算符的模式
【发布时间】:2012-08-31 10:38:01
【问题描述】:

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

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

===file2(制表符分隔)===
1个
2个
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,谢谢。

【问题讨论】:

    标签: java apache-pig


    【解决方案1】:

    您没有使用 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;
    

    至于问题的根源,我猜测一下,可能与这个(as stated in Pig Documentation)结合 pig 的运行周期优化有关:

    如果您 FLATTEN 一个内部架构为空的包,则结果关系的架构为空。

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

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

    This is the complete -explain- output for script 2this is for script 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 实际上是一个java String,表示为字节数组。由于这个 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 尝试(并成功)进行从 bytearrayinteger 的显式转换操作。

    【讨论】:

    • 是的,我一开始用的是PigStorage,但是过程中生成了像'_'这样的数据格式,所以只能STRSPLIT
    • 而“-”是我的粗心,实际上代码是正确的
    • 感谢您的回答。但是我还是不明白,当你描述a1时,Pig给出了a1: {num: int,ch: chararray},为什么这个schema不能用在加入运算符。还有script2和script3有什么区别,一个有filed一个没有
    • 所以你的意思是在**AS子句**中发生了强制转换异常,但是dump a1没有引起异常
    • 强制转换异常是由 AS 子句引起的。虽然它(AS 子句)在您调用转储或存储之前不会被评估。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    • 2018-03-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多