2015-07-28 3 views
1

Я новичок в Apache Pig. Я хочу разбить и сгладить следующий ввод в мой требуемый результат, например, кто все это просматривает.Невозможно избежать дублирования удаления в Apache Pig

Мой вход: (UserId, ProductID)

12345 123456,23456,987653 
23456 23456,123456,234567 
34567 234567,765678,987653 

Моя требуемая выходная мощность: (ProductID, UserId)

123456 12345 
123456 23456 
23456 12345  
23456 23456 
987653 12345 
987653 34567 
234567 23456 
234567 34567 
765678 34567 

Мои Свиньи Сценарии:

a = load '/home/hadoopuser/ips' using PigStorage('\t') as (key:chararray, val:chararray); 
b = foreach a generate key as ky1, FLATTEN(TOKENIZE(val)) as vl1; 
c = group b by vl1; 
d = foreach c generate group as vl2, $1 as ky2; 
e = foreach d generate vl2, BagToString(ky2) as kyy; 
f = foreach e generate vl2 as vl3,FLATTEN(STRSPLIT(kyy,'_')) as ky3; 
g = foreach f generate vl3, FLATTEN(TOKENIZE(ky3)) as kk1; 
dump g; 

я получил следующее выход, который устраняет повторяющиеся (повторяющиеся) значения,

(23456,12345) 
(123456,12345) 
(234567,23456) 
(765678,34567) 
(987653,12345) 

Я не знаю, как решить эту проблему. Может ли кто-нибудь помочь мне решить эту проблему? и как это сделать простым способом?

ответ

0

Ну, вторая строка вашего кода делает именно то, что вы хотите, она просто отображает клиента сначала и продукт второй. Поместите сначала FLATTEN, а затем key часть:

a = load '/home/hadoopuser/ips' using PigStorage('\t') as (key:chararray, val:chararray); 
b = foreach a generate FLATTEN(TOKENIZE(val)) as ProductId, key as UserId; 
dump b; 

(123456,12345) 
(23456,12345) 
(987653,12345) 
(23456,23456) 
(123456,23456) 
(234567,23456) 
(234567,34567) 
(765678,34567) 
(987653,34567) 

Как почему вы получаете только один результат за PRODUCTID с текущим кодом, вы группировку по ProductID, что дает вам одну строку на другую ProductId с мешком который содержит всех клиентов, которые рассматривали этот продукт. Затем преобразовать эту сумку в огромную строку разделенных _, чтобы преобразовать его снова в той же сумке, как и раньше:

d = foreach c generate group as vl2, $1 as ky2; 
e = foreach d generate vl2, BagToString(ky2) as kyy; 
f = foreach e generate vl2 as vl3,FLATTEN(STRSPLIT(kyy,'_')) as ky3; 

BagToString UDF преобразует пакет в строку, соединяя различные значения в сумке отделенной пользовательским разделителем, который по умолчанию равен _. В следующей строке, однако, вы разделили ее на _, в результате чего в том же пакете, что и раньше. Однако у вас есть FLATTEN этот мешок, поэтому теперь вместо того, чтобы иметь строку с ProductId и сумкой, у вас есть строка с несколькими полями, являющаяся первым ProductId, и следующие поля для всех клиентов, которые просмотрели продукт:

Перед Свести:

(23456,{(23456,23456),(12345,23456)}) 
(123456,{(23456,123456),(12345,123456)}) 
(234567,{(34567,234567),(23456,234567)}) 
(765678,{(34567,765678)}) 
(987653,{(34567,987653),(12345,987653)}) 

После Свести:

(23456,23456,23456,12345,23456) 
(123456,23456,123456,12345,123456) 
(234567,34567,234567,23456,234567) 
(765678,34567,765678) 
(987653,34567,987653,12345,987653) 

И здесь кроется ошибка. У вас есть только одна строка для каждого из продуктов и несколько полей в каждой строке для каждого клиента. При применении последнего foreach вы выбираете первое поле (продукт) и второе (в первую очередь клиентов), отбрасывая остальных клиентов в каждой строке.

+0

Привет, Balduz, Спасибо за ваш ответ. Он работает правильно, и я понял эту проблему очень хорошо благодаря вашему четкому объяснению. –

Смежные вопросы