Не удалось избежать дублирования удаления в Apache Pig

61
4

Я новичок в 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)

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

спросил(а) 2021-01-19T22:24:07+03:00 2 месяца, 3 недели назад
1
Решение
114

Ну, вторая строка вашего кода делает именно то, что вы хотите, оно просто отображает клиента сначала, а второе. Поместите сначала 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 с сумкой, в которой содержатся все клиенты, которые рассматривали этот продукт. Затем вы конвертируете эту сумку в огромную строку, разделенную _, чтобы преобразовать ее снова в ту же сумку, что и раньше:

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 и следующие поля для всех клиентов, просмотревших продукт:

Перед FLATTEN:

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

После FLATTEN:

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

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

ответил(а) 2021-01-19T22:24:07+03:00 2 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема