Pig 10.0 - group the tuples and merge bags in a foreach
apache-pig, hadoop
Solution
I finally managed to achieve the wanted behavior. A self contained example of my solution follows:
Data file:
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
Code:
-- 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;
Describe:
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)
Since the code uses a FOREACH nested in a FOREACH it requires Pig > 10.0.
I will let the question as unresolved for a few days since a cleaner solution probably exists.
Problem
I'm using `Pig 10.0`. I want to Merge bags in a foreach. Let's say I have the following `visitors` alias: ``` (a, b, {1, 2, 3, 4}), (a, d, {1, 3, 6}), (a, e, {7}), (z, b, {1, 2, 3}) ``` I want to group the tuples on the first field and merge the bags with a set semantic to get the following following tuples: ``` ({1, 2, 3, 4, 6, 7}, a, 6) ({1, 2, 3}, z, 3) ``` The first field is the union of the bags with a set semantic. The second field of the tuple is the group field. The third field is the number items in the bag. I tried several variations around the following code (replaced SetUnion by Group/Distinct etc.) but always failed to achieve the wanted behavior: ``` 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; ``` Can you explain where I'm wrong and how to implement the desired behavior?