Apache pig Pig中多袋单元组到多元组的转换

Apache pig Pig中多袋单元组到多元组的转换,apache-pig,Apache Pig,我有一句话如下: evnt=redeem&lid=1030023&upt=1679&pid=000000000001076056,000000000001072654,000000000001067925&ppt=996,246,366&qty=1,2,3 logs = foreach logs generate REGEX_EXTRACT(original_path, 'lid=([^&]+)', 1)

我有一句话如下:

evnt=redeem&lid=1030023&upt=1679&pid=000000000001076056,000000000001072654,000000000001067925&ppt=996,246,366&qty=1,2,3
logs = foreach logs generate
                    REGEX_EXTRACT(original_path, 'lid=([^&]+)', 1) as login_id,
                    FLATTEN(TOKENIZE(REPLACE(REGEX_EXTRACT(original_path, '.*pid=([^&]+)', 1), ',', ' '))) as pid;
我感兴趣的是从行中提取lid、pid、ppt和qty,并为pid、ppt和qty中的每个条目创建一个元组。请注意,这些规则是:

  • 除盖子外的所有东西都可以有多个值。如果值中有逗号,则有多个值
  • pid可以有多个值,这些值与其他值的顺序相同。例如,
    lid=4&pid=1,2&qty=2,3&ppt=123232
    表示如果
    lid=4
    pid=1
    qty=2
    ppt=123
    ,如果
    lid=4
    pid=2
    qty=3
    ppt=232
  • ppt遵循与数量相同的规则,因为它与pid相关
我已经能够通过以下方式完成这些字段的lid和pid:

evnt=redeem&lid=1030023&upt=1679&pid=000000000001076056,000000000001072654,000000000001067925&ppt=996,246,366&qty=1,2,3
logs = foreach logs generate
                    REGEX_EXTRACT(original_path, 'lid=([^&]+)', 1) as login_id,
                    FLATTEN(TOKENIZE(REPLACE(REGEX_EXTRACT(original_path, '.*pid=([^&]+)', 1), ',', ' '))) as pid;
这给了我:

1030023    000000000001076056
1030023    000000000001072654
1030023    000000000001067925
但是,我也希望对其他两个字段执行此操作(将其保留为三个元组),并且在同一个foreach语句中进行多个展平并不能满足我的要求

1030023    000000000001076056    996    1
1030023    000000000001072654    246    2
1030023    000000000001067925    366    3

我猜这将需要一个UDF,但我想知道是否有其他方法可以绕过它,只使用Pig中提供的函数。

我有点不确定您希望输出的确切程度,但这是在纯Pig中可以做到的

在我看来,当你不知道字段的数目时,元组在pig中有点笨拙。因此,如果数字的顺序不重要,我建议使用袋子。在这种情况下,TOKENIZE将以包的形式创建输出,STRSPLIT将以元组的形式创建输出

此代码:

A = LOAD 'logs' AS (total:chararray);                                   
B = FOREACH A {  
    -- In this case a nested foreach makes the code much easier to read.                                                            
    lid = REGEX_EXTRACT(total, 'lid=([^&]+)', 1) ;
    -- TOKENIZE splits on ',' creating a bag.
    pid = TOKENIZE(REGEX_EXTRACT(total, '.*pid=([^&]+)', 1), ',') ;
    -- STRSPLIT splits on ',' creating a tuple.
    ppt = STRSPLIT(REGEX_EXTRACT(total, '.*ppt=([^&]+)', 1), ',') ;             
    qty = STRSPLIT(REGEX_EXTRACT(total, '.*qty=([^&]+)', 1), ',') ;             
    GENERATE lid as lid, FLATTEN(pid) as pid, ppt as ppts, qty as qtys ;         
}  
生成此架构和输出:

B: {lid: chararray,pid: chararray,ppts: (),qtys: ()}
(1030023,000000000001076056,(996,246,366),(1,1,1))
(1030023,000000000001072654,(996,246,366),(1,1,1))
(1030023,000000000001067925,(996,246,366),(1,1,1))
使用TOKENIZE生成包而不是元组创建此输出:

B: {lid: chararray,pid: chararray,ppts: {tuple_of_tokens: (token: chararray)},qtys: {tuple_of_tokens: (token: chararray)}}
(1030023,000000000001076056,{(996),(246),(366)},{(1),(1),(1)})
(1030023,000000000001072654,{(996),(246),(366)},{(1),(1),(1)})
(1030023,000000000001067925,{(996),(246),(366)},{(1),(1),(1)})
如果希望pid也是一个元组,则只需更改以下两行:

pid = TOKENIZE(REGEX_EXTRACT(total, '.*pid=([^&]+)', 1), ',') ;   
GENERATE lid as lid, FLATTEN(pid) as pid, ppt as ppts, qty as qtys ; 
致:


我有点不确定您希望输出的确切程度,但这是在纯pig中如何实现的

在我看来,当你不知道字段的数目时,元组在pig中有点笨拙。因此,如果数字的顺序不重要,我建议使用袋子。在这种情况下,TOKENIZE将以包的形式创建输出,STRSPLIT将以元组的形式创建输出

此代码:

A = LOAD 'logs' AS (total:chararray);                                   
B = FOREACH A {  
    -- In this case a nested foreach makes the code much easier to read.                                                            
    lid = REGEX_EXTRACT(total, 'lid=([^&]+)', 1) ;
    -- TOKENIZE splits on ',' creating a bag.
    pid = TOKENIZE(REGEX_EXTRACT(total, '.*pid=([^&]+)', 1), ',') ;
    -- STRSPLIT splits on ',' creating a tuple.
    ppt = STRSPLIT(REGEX_EXTRACT(total, '.*ppt=([^&]+)', 1), ',') ;             
    qty = STRSPLIT(REGEX_EXTRACT(total, '.*qty=([^&]+)', 1), ',') ;             
    GENERATE lid as lid, FLATTEN(pid) as pid, ppt as ppts, qty as qtys ;         
}  
生成此架构和输出:

B: {lid: chararray,pid: chararray,ppts: (),qtys: ()}
(1030023,000000000001076056,(996,246,366),(1,1,1))
(1030023,000000000001072654,(996,246,366),(1,1,1))
(1030023,000000000001067925,(996,246,366),(1,1,1))
使用TOKENIZE生成包而不是元组创建此输出:

B: {lid: chararray,pid: chararray,ppts: {tuple_of_tokens: (token: chararray)},qtys: {tuple_of_tokens: (token: chararray)}}
(1030023,000000000001076056,{(996),(246),(366)},{(1),(1),(1)})
(1030023,000000000001072654,{(996),(246),(366)},{(1),(1),(1)})
(1030023,000000000001067925,{(996),(246),(366)},{(1),(1),(1)})
如果希望pid也是一个元组,则只需更改以下两行:

pid = TOKENIZE(REGEX_EXTRACT(total, '.*pid=([^&]+)', 1), ',') ;   
GENERATE lid as lid, FLATTEN(pid) as pid, ppt as ppts, qty as qtys ; 
致:


如果你能用正则表达式得到前两个字段,我不明白为什么你不能同样得到另外两个字段。你能发布你尝试过的吗?问题不是如何从字符串中解析数据。它是如何将一个包含四个字段的元组转换为三个独立的元组(三个元组是因为第一个字段id是相同的)。我通过创建一个UDF解决了这个问题。我只是想知道是否有一种方法可以做到这一点,而不是写一个猪UDF。在看到两个回答后,我更新了这个问题,使之更加具体,这两个回答暗示我的问题过于抽象。如果你可以使用正则表达式来获得前两个字段,我不明白为什么你不能同样获得其他两个字段。你能发布你尝试过的吗?问题不是如何从字符串中解析数据。它是如何将一个包含四个字段的元组转换为三个独立的元组(三个元组是因为第一个字段id是相同的)。我通过创建一个UDF解决了这个问题。我只是想知道是否有一种方法可以在不写猪UDF的情况下做到这一点。在看到两个回答暗示我的问题过于抽象后,我更新了问题,使之更加具体。这是我尝试过的事情之一。最后,我希望输出的格式与问题中最后一个示例的格式相同。啊,等等。因此,如果
qty
1,2,3
而不是
1,1,1
,那么输出将是:
1030023 00000000000107605699611030023 0000000000010726542461030023 000000000001067925363
?这是我尝试过的事情之一。最后,我希望输出的格式与问题中最后一个示例的格式相同。啊,等等。因此,如果
qty
1,2,3
而不是
1,1,1
,那么输出将是:
1030023 00000000000107605699611030023 0000000000010726542461030023 000000000001067925363