Pig 10.0 - 将元组组合在一起并将袋子合并在一个foreach中

时间:2013-03-27 14:07:13

标签: hadoop apache-pig

我正在使用Pig 10.0。我想在一个foreach合并袋子。假设我有以下visitors别名:

(a, b, {1, 2, 3, 4}),
(a, d, {1, 3, 6}),
(a, e, {7}),
(z, b, {1, 2, 3})

我想在第一个字段上对元组进行分组,并使用set语义合并包,以获得以下元组:

({1, 2, 3, 4, 6, 7}, a, 6) 
({1, 2, 3}, z, 3) 

第一个字段是带有集合语义的包的并集。元组的第二个字段是组字段。第三个字段是包中的数字项。

我尝试了以下代码的几种变体(用Group / Distinct等替换了SetUnion)但总是无法实现想要的行为:

DEFINE SetUnion        datafu.pig.bags.sets.SetUnion();

grouped = GROUP visitors by (FirstField);
merged = FOREACH grouped {
    VU = SetUnion(visitors.ThirdField);
    GENERATE 
        VU        as Vu,
        group     as FirstField,
        COUNT(VU) as Cnt;
    }
dump merged;

你能解释我错在哪里以及如何实现所期望的行为吗?

2 个答案:

答案 0 :(得分:4)

我终于成功实现了通缉行为。我的解决方案的一个自包含的例子如下:

数据文件:

a       b       1
a       b       2
a       b       3
a       b       4
a       d       1
a       b       3
a       b       6
a       e       7
z       b       1
z       b       2
z       b       3

代码:

-- Prepare data
in = LOAD 'data' USING PigStorage() 
        AS (One:chararray, Two:chararray, Id:long);

grp = GROUP in by (One, Two);
cnt = FOREACH grp {
        ids = DISTINCT in.Id;
        GENERATE
                ids        as Ids,
                group.One  as One,
                group.Two  as Two,
                COUNT(ids) as Count;
}       

-- Interesting code follows
grp2 = GROUP cnt by One;
cnt2 = FOREACH grp2 {
        ids = FOREACH cnt.Ids generate FLATTEN($0);
        GENERATE
                ids  as Ids,
                group      as One,
                COUNT(ids) as Count;
}               

describe cnt2;
dump grp2;
dump cnt2;

说明:

Cnt: {Ids: {(Id: long)},One: chararray,Two: chararray,Count: long}

GRP2:

(a,{({(1),(2),(3),(4),(6)},a,b,5),({(1)},a,d,1),({(7)},a,e,1)})
(z,{({(1),(2),(3)},z,b,3)})

CNT2:

({(1),(2),(3),(4),(6),(1),(7)},a,7)
({(1),(2),(3)},z,3)

由于代码使用嵌套在FOREACH中的FOREACH,因此它需要Pig> 10.0。

由于可能存在更清晰的解决方案,我会在几天内将问题解决。

答案 1 :(得分:0)

为此找到了一个更简单的解决方案。

current_input = load' /idn/home/ksing143/tuple_related_data/tough_grouping.txt'使用PigStorage()AS(col1:chararray,col2:chararray,col3:int);

/ * 但是我们不需要第2列。因此消除以避免混淆 * /

relevant_input = foreach current_input generate col1,col3;

relevant_distinct = DISTINCT related_input;

related_grouped = group related_distinct by col1;

/ * 这将提供 * /

(A,{(A,1),(A,2),(A,3),(A,4),(A,6),(A,7)})

(Z,{(z,1),(Z,2),(Z,3)})

relevant_grouped_advance = foreach related_grouped generate(relevant_distinct.col3)as col3,group,COUNT(relevant_distinct.col3)as count_val;

/ *这将产生预期的结果* /

({(1),(2),(3),(4),(6),(7)},A,6)

({(1),(2),(3)},Z,3)