1

次のようなコードを含む豚のスクリプトがあります。

scores = LOAD 'file' as (id:chararray, scoreid:chararray, score:int);
scoresGrouped = GROUP scores by id;
top10s = foreach scoresGrouped{
    sorted = order scores by score DESC;
    sorted10 = LIMIT sorted 10;
    GENERATE group as id, sorted10.scoreid as top10candidates;
};

それは私に次のようなバッグを手に入れます

 id1, {(scoreidA),(scoreidB),(scoreIdC)..(scoreIdFoo)}

ただし、アイテムのインデックスも含めたいので、次のような結果が得られます

 id1, {(scoreidA,1),(scoreidB,2),(scoreIdC,3)..(scoreIdFoo,10)}

ネストされた foreach に何らかの方法でインデックスを含めることは可能ですか、それとも後で追加するために独自の UDF を作成する必要がありますか?

4

2 に答える 2

2

バッグ内の要素にインデックスを付けるには、LinkedInのDataFuプロジェクトからUDFを列挙するを使用できます。

register '/path_to_jar/datafu-0.0.4.jar';
define Enumerate datafu.pig.bags.Enumerate('1');
scores = ...
...
result = foreach top10s generate id, Enumerate(top10candidates);
于 2012-12-22T14:26:51.517 に答える
2

UDFが必要です。その引数は、ランクを追加するソートされたバッグだけです。私は以前に同じ必要がありました。少し時間を節約するためのexec関数は次のとおりです。

public DataBag exec(Tuple b) throws IOException {
    try {
        DataBag bag = (DataBag) b.get(0);
        Iterator<Tuple> it = bag.iterator();
        while (it.hasNext()) {
            Tuple t = (Tuple)it.next();
            if (t != null && t.size() > 0 && t.get(0) != null) {
                t.append(n++);
            }
            newBag.add(t);
        }
    } catch (ExecException ee) {
        throw ee;
    } catch (Exception e) {
        int errCode = 2106;
        String msg = "Error while computing item number in " + this.getClass().getSimpleName();
        throw new ExecException(msg, errCode, PigException.BUG, e);           
    }

    return newBag;
}

(カウンターnは関数外のクラス変数として初期化されexecます。)

また、アキュムレータインターフェイスを実装することもできます。これにより、バッグ全体がメモリに収まらない場合でも、これを実行できます。(COUNT組み込み関数がこれを行います。)メソッドとで設定n = 1L;することを忘れないでください。それ以外はすべて同じです。cleanup()return newBag;getValue()

于 2012-12-21T14:14:19.120 に答える