1

私はPigがまったく初めてです。iid フィールドを使用して 2 つのファイル A と B を結合したいのですが、A にない (B からの) iid を出力に含めたくありません。これは簡単に思えますが、正しく行う方法がわかりません。

ユニオンのみを持つサンプルコードは次のとおりです。

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

助けてくれてどうもありがとう!

4

2 に答える 2

3

を使用して同じキーでレコードを整理しますが、の望ましくない外積COGROUPは避けてください。JOIN次に、のレコードが含まFILTERれるバッグbが空であるかどうかによって、2つのリレーションに分割し、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);
c = COGROUP a BY iid, b BY iid;
c_filt = FILTER c BY NOT IsEmpty(b);
a_new = FOREACH c_filt GENERATE group AS iid, FLATTEN(a);
b_new = FOREACH c_filt GENERATE group AS iid, FLATTEN(b);
out = UNION ONSCHEMA a_new, b_new;
singled = DISTINCT out;
STORE (ORDER singled BY iid) INTO '$output';

ただし、私はこのソリューションのファンではありません。このような単純な操作には、行が多すぎて新しい関係があります。本当に必要なのは、2つのバッグを1つにまとめる方法です。Pigは明らかにこれを提供していません(提供している場合は、このSOの質問に答えてください)。ただし、これを行うための単純な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;
    }
}

このUDFを使用すると、ソリューションは次のようになります。

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);
c = FOREACH (COGROUP a BY iid, b BY iid) GENERATE group AS iid, MERGE(a,b) AS bag;
out = FOREACH c {
    uniq = DISTINCT bag;
    GENERATE iid, FLATTEN(bag);
};
STORE (ORDER out BY iid) INTO '$output';

このアプローチのもう1つの利点は、複数の入力がある場合、FOREACHの後に数秒実行する必要がないことCOGROUPです。引数を追加するだけMERGEです:

c = FOREACH (COGROUP a BY iid, b BY iid, ..., z BY iid)
    GENERATE group AS iid, MERGE(a,b,...,z) AS bag;
于 2012-11-16T14:12:37.920 に答える
2

This one here should solve your problem:

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;
于 2012-11-16T09:32:40.477 に答える