1

我有如下一行:

evnt=redeem&lid=1030023&upt=1679&pid=000000000001076056,000000000001072654,000000000001067925&ppt=996,246,366&qty=1,2,3

我有兴趣从行中提取盖子、pid、ppt 和 qty,并为 pid、ppt 和 qty 中的每个条目创建一个元组。请注意,规则是​​:

  • 除了盖子之外的所有东西都可以有多个值。当值中有逗号时,有多个值
  • pid 可以有多个值,并且这些值与其他值具有相同的顺序。例如,lid=4&pid=1,2&qty=2,3&ppt=123,232表示 if lid=4and pid=1then qty=2and ppt=123,and if lid=4and pid=2then qty=3and ppt=232
  • ppt 遵循与 qty 相同的规则,因为它与 pid 相关。

我已经能够通过以下方式为这些字段的盖子和 pid 完成此操作:

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 中提供的函数来解决它。

4

1 回答 1

1

我有点不确定您希望输出的确切程度,但这就是您如何在纯猪中做到这一点。

在我看来,当你不知道字段的数量时,元组在猪中有点尴尬。因此,如果数字的顺序无关紧要,我建议使用袋子。在这种情况下,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 ; 

至:

pid = STRSPLIT(REGEX_EXTRACT(total, '.*pid=([^&]+)', 1), ',') ;   
GENERATE lid as lid, pid as pid, ppt as ppts, qty as qtys ; 
于 2013-07-01T16:04:33.700 回答