Apache pig hadoop pig脚本-与条件联合

Apache pig hadoop pig脚本-与条件联合,apache-pig,hadoop-streaming,Apache Pig,Hadoop Streaming,我对猪完全陌生。我想使用iid字段合并两个文件A和B,但我不希望输出中有A没有的来自B的iid。这似乎很简单,但我不知道如何正确地做 以下是仅包含union的示例代码: a = load '$input' as (iid:int, field:chararray, v1:chararray, v2:chararray, v3:chararray); b = load '$data' as (iid:int, field:chararray, v1:chararray, v2:chararray,

我对猪完全陌生。我想使用iid字段合并两个文件A和B,但我不希望输出中有A没有的来自B的iid。这似乎很简单,但我不知道如何正确地做

以下是仅包含union的示例代码:

a = load '$input' as (iid:int, field:chararray, v1:chararray, v2:chararray, v3:chararray);
b = load '$data' as (iid:int, field:chararray, v1:chararray, v2:chararray, v3:chararray);
out = union onschema a,b;
singled = distinct out;
ordered = order singled by iid;
store ordered into '$output';
下面是仅包含3列的示例数据,用于描述我所期望的内容。请注意,字段实际上是以制表符分隔的

样本数据A:

1  Name   Tom Linkon
1  Title  Professor
2  Name   Whatever
2  Title  Worker
样本数据B:

1  City  New York
2  City  Columbus
3  City  Fake fake
4  City  Blah Bla
样本输出

1  Name   Tom Linkon
1  Title  Professor
1  City   New York
2  Name   Whatever
2  Title  Worker
2  City   Columbus

非常感谢你的帮助

这里的这个应该可以解决您的问题:

f1 = LOAD '/user/hadoop/f1' USING PigStorage('\t') AS (id_f1:int, key_f1:chararray, value_f1:chararray);
f2 = LOAD '/user/hadoop/f2' USING PigStorage('\t') AS (id_f2:int, key_f2:chararray, value_f2:chararray);
f3 = JOIN f1 by id_f1 LEFT OUTER, f2 BY id_f2;
f4 = FOREACH f3 GENERATE id_f1, key_f1, value_f1;
f5 = FOREACH f3 GENERATE id_f2, key_f2, value_f2;
f6 = UNION f4, f5;
f7 = DISTINCT f6;
f8 = ORDER f7 BY $0;
DUMP f8;

这里的这个应该可以解决您的问题:

f1 = LOAD '/user/hadoop/f1' USING PigStorage('\t') AS (id_f1:int, key_f1:chararray, value_f1:chararray);
f2 = LOAD '/user/hadoop/f2' USING PigStorage('\t') AS (id_f2:int, key_f2:chararray, value_f2:chararray);
f3 = JOIN f1 by id_f1 LEFT OUTER, f2 BY id_f2;
f4 = FOREACH f3 GENERATE id_f1, key_f1, value_f1;
f5 = FOREACH f3 GENERATE id_f2, key_f2, value_f2;
f6 = UNION f4, f5;
f7 = DISTINCT f6;
f8 = ORDER f7 BY $0;
DUMP f8;
使用COGROUP组织具有相同键的记录,但避免JOIN的不希望的叉积。然后根据带有b记录的包是否为空进行过滤,将其拆分为两个关系,然后进行并集:

然而,我并不喜欢这个解决方案——对于这样一个简单的操作来说,有太多的线路和新的关系。真正需要的是一种将两个袋子组合成一个袋子的方法。猪显然没有提供,但如果有,请回答。不过,您可以编写一个简单的UDF来实现这一点:

public class MERGE extends EvalFunc<DataBag> {
    public DataBag exec(Tuple input) throws IOException {
        DataBag b = new DefaultDataBag();
        try {
            if (input != null)
                for (int i = 0; i < input.size(); i++)
                    b.addAll((DataBag) input.get(i));
        } catch (Exception e) { return null; }
        return b;
    }
}
这种方法的另一个优点是,如果您有多个输入,则不需要在COGROUP之后执行多个foreach。只需添加更多要合并的参数:

使用COGROUP组织具有相同键的记录,但避免JOIN的不希望的叉积。然后根据带有b记录的包是否为空进行过滤,将其拆分为两个关系,然后进行并集:

然而,我并不喜欢这个解决方案——对于这样一个简单的操作来说,有太多的线路和新的关系。真正需要的是一种将两个袋子组合成一个袋子的方法。猪显然没有提供,但如果有,请回答。不过,您可以编写一个简单的UDF来实现这一点:

public class MERGE extends EvalFunc<DataBag> {
    public DataBag exec(Tuple input) throws IOException {
        DataBag b = new DefaultDataBag();
        try {
            if (input != null)
                for (int i = 0; i < input.size(); i++)
                    b.addAll((DataBag) input.get(i));
        } catch (Exception e) { return null; }
        return b;
    }
}
这种方法的另一个优点是,如果您有多个输入,则不需要在COGROUP之后执行多个foreach。只需添加更多要合并的参数:


你需要来自a和b的元组以单独的元组结束吗?或者当iid的值匹配时,它们可以以相同的元组结束吗?@Fred我刚刚添加了样本数据a,B和输出我问题中的数据样本以供澄清:您需要来自a和B的元组以单独的元组结束,还是当iid的值匹配时,它们以相同的元组结束可以?@Fred我刚刚添加了样本数据a,B和输出我问题中的数据样本以供澄清:这也将丢弃A中与B不匹配的记录,因此最好执行f3=通过id_f1左外连接f1,通过id_f2连接f2;这也将丢弃A中与B中不匹配的记录,因此最好执行f3=通过id_f1左外连接f1,通过id_f2连接f2;这太棒了,温妮!我会尝试一下,让你知道!非常感谢您的建议,这非常有帮助,我真的很感激!:温妮,我用了第一种方法,效果很好。我刚刚尝试了第二种方法,但在合并代码行中出现如下错误。你知道这件事吗?[main]ERROR org.apache.pig.tools.grunt.grunt-ERROR 1200:语法错误,您所在位置或附近的意外符号出现语法错误,并非您不知道。Pig的错误消息可能非常隐晦,所以很难说您的问题是什么。你最好的办法是针对这个错误发布一个新的问题,以及导致这个错误的代码。这太棒了,Winnie!我会尝试一下,让你知道!非常感谢您的建议,这非常有帮助,我真的很感激!:温妮,我用了第一种方法,效果很好。我刚刚尝试了第二种方法,但在合并代码行中出现如下错误。你知道这件事吗?[main]ERROR org.apache.pig.tools.grunt.grunt-ERROR 1200:语法错误,您所在位置或附近的意外符号出现语法错误,并非您不知道。Pig的错误消息可能非常隐晦,所以很难说您的问题是什么。您最好的选择是针对此错误发布一个新问题,以及导致此错误的代码。
c = FOREACH (COGROUP a BY iid, b BY iid, ..., z BY iid)
    GENERATE group AS iid, MERGE(a,b,...,z) AS bag;