Is it possible to cross-join a row in a relation with a tuple in that row in Pig?
I have a set of data that shows users, collections of fruit they like, and home city:
Alice\tApple:Orange\tSacramento
Bob\tApple\tSan Diego
Charlie\tApple:Pineapple\tSacramento
I would like to create 开发者_运维百科a pig query that correlates the number of users that enjoy tyeps of fruits in different cities, where the results from the query for the data above would look like this:
Apple\tSacramento\t2
Apple\tSan Diego\t1
Orange\tSacramento\t1
Pineapple\tSacramento\t1
The part I can't figure out is how to cross join the split fruit rows with the rest of the data from the same row, so:
Alice\tApple:Orange\tSacramento
becomes:
Alice\tApple\tSacramento
Alice\tOrange\tSacramento
I know I can use TOKENIZE to split the string 'Apple:Orange' into the tuple ('Apple', 'Orange'), but I don't know how to get the cross product of that tuple with the rest of the row ('Alice').
One brute-force solution I came up with is to use the streaming to run the input collection through an external program, and handle the "cross join" to produce multiple rows per row there.
This seems like it should be unnecessary though. Are there better ideas?
You should use FLATTEN
, which works great with TOKENIZE
to do stuff like this.
b = FOREACH a GENERATE name, FLATTEN(TOKENIZE(fruits)) as fruit, city;
FLATTEN
takes a bag and "flattens" it out across different rows. TOKENIZE
breaks your fruits out into a bag (not a tuple like you said), and then FLATTEN
does the cross-like behavior like you are looking for. I point out that it is a bag and not a tuple, because FLATTEN
is overloaded and behaves differently with tuples.
I first learned of the FLATTEN
/TOKENIZE
technique in the canonical word count example, in which is tokenizes a word, then flattens the words out into rows.
精彩评论