http://hi.baidu.com/parrot9/item/080d77370aa1884b3075a1a3
今天在写pig处理数据的时候遇到的这样的问题:
a = LOAD 'dataA' AS (fa1, fa2);
b = LOAD 'dataB' AS (fb1, fb2);
c = JOIN a BY fa1, b BY fb1;
d = FOREACH c GENERATE a.fa1, a.fa2;
STORE d INTO 'output';
这个脚本的作用很简单,就是数据dataA有fa1, fa2两个域,dataB有fb1, fb2两个域,我想要打印出a中所有满足fa1 == b的fb1域的值的记录,所以用JOIN这么写肯定是没有问题。但是这个pig脚本运行起来会报一个错: Scalar has more than one row in the output. 完全不make sense的一个提示。后来搜了搜,才知道应该要把上面脚本中GENERATE一句的"a.fa1"改成"a::fa1"。不过为什么直接用a.fa1来引用a中的fa1值不行呢?这跟JOIN的输出结果的格式有关系。pig中可以用illustrate 命令来从输入数据中sample一些数据出来试运行,并且给出输入输出的格式。所以我们illustrate一个c,得到
---------------------------------------------| A | fa1:bytearray | fa2:bytearray | ---------------------------------------------| | 3 | 4 | | | 3 | 4 | ------------------------------------------------------------------------------------------| B | fb1:bytearray | fb2:bytearray | ---------------------------------------------| | 3 | 6 | | | 3 | 6 | ------------------------------------------------------------------------------------------------------------------------------------------| C | A::fa1:bytearray | A::fa2:bytearray | B::fb1:bytearray | B::fb2:bytearray | ---------------------------------------------------------------------------------------------| | 3 | 4 | 3 | 6 | | | 3 | 4 | 3 | 6 | | | 3 | 4 | 3 | 6 | | | 3 | 4 | 3 | 6 | ---------------------------------------------------------------------------------------------
所以不难理解为什么要用"A::fa1"而不用"A.fa1",因为在C里面已经不存在原来A里面的结构了,只有一个名为"A::fa1"的域。同样的功能还可以用COGROUP来实现,所以上述的代码将改为e = COGROUP a BY fa1, b BY fb1; 再illustrate 一下e -------------------------------------------------------------------------------------------------------------------------------------------------| E | group:bytearray | A:bag{:tuple(fa1:bytearray,fa2:bytearray)} | B:bag{:tuple(fb1:bytearray,fb2:bytearray)} | -------------------------------------------------------------------------------------------------------------------------------------------------| | 3 | {(3, 4), (3, 4)} | {(3, 6), (3, 6)} | -------------------------------------------------------------------------------------------------------------------------------------------------用COGROUP命令就还保留了原来A里面的数据结构,并且在外层加一个bag。所以要打印e的结果,就要先FLATTEN(A),把bag这个数据结构展开,然后再拿FLATTEN之后的东西用 .fa1 的方式来取到。