Pig Latin(在 foreach 循环中过滤第二个数据源)

Posted

技术标签:

【中文标题】Pig Latin(在 foreach 循环中过滤第二个数据源)【英文标题】:Pig Latin (Filter 2nd data source in foreach loop) 【发布时间】:2013-06-29 00:01:38 【问题描述】:

我有 2 个数据源。一个包含 api 调用列表,另一个包含所有相关的身份验证事件。每个 Api 调用可以有多个 Auth 事件,我想找到以下 auth 事件: a) 包含与 Api 调用相同的“标识符” b) 发生在 Api 调用后的一秒内 c) 是经过上述过滤后最接近 Api Call 的。

我曾计划在 foreach 循环中遍历每个 ApiCall 事件,然后在 authevents 上使用过滤器语句来找到正确的事件 - 但是,这似乎是不可能的 (USING Filter in a Nested FOREACH in PIG)

谁能提出其他方法来实现这一点。如果有帮助,这是我尝试使用的 Pig 脚本:

apiRequests = LOAD '/Documents/ApiRequests.txt' AS (api_fileName:chararray, api_requestTime:long, api_timeFromLog:chararray, api_call:chararray, api_leadString:chararray, api_xmlPayload:chararray, api_sourceIp:chararray, api_username:chararray, api_identifier:chararray);
authEvents = LOAD '/Documents/AuthEvents.txt' AS (auth_fileName:chararray, auth_requestTime:long, auth_timeFromLog:chararray, auth_call:chararray, auth_leadString:chararray, auth_xmlPayload:chararray, auth_sourceIp:chararray, auth_username:chararray, auth_identifier:chararray);
specificApiCall = FILTER apiRequests BY api_call == 'CSGetUser';                 -- Get all events for this specific call
match = foreach specificApiCall                                                 -- Now try to get the closest mathcing auth event
        filtered1 = filter authEvents by auth_identifier == api_identifier;      -- Only use auth events that have the same identifier (this will return several)
        filtered2 = filter filtered1 by (auth_requestTime-api_requestTime)<1000; -- Further refine by usings auth events within a second on the api call's tiime
        sorted = order filtered2 by auth_requestTime;                            -- Get the auth event that's closest to the api call
        limited = limit sorted 1;
        generate limited;
        ;
dump match;

【问题讨论】:

【参考方案1】:

嵌套FOREACH 不适用于在循环第一个关系时处理第二个关系。这是因为当您的关系中有一个包并且您想使用该包时,就好像它是它自己的关系一样。您不能同时使用apiRequestsauthEvents,除非您先进行某种连接或分组,以将您需要的所有信息放入一个关系中。

如果您不需要将自己限制为单个授权事件,那么您的任务在概念上与 JOINFILTER 配合得很好:

allPairs = JOIN specificApiCall BY api_identifier, authEvents BY auth_identifier;
match = FILTER allPairs BY (auth_requestTime-api_requestTime)<1000;

现在所有信息都集中在一起了,您可以在 GROUP match BY api_identifier 后跟一个嵌套的 FOREACH 来挑选单个事件。

但是,如果您使用 COGROUP 运算符(类似于 JOIN 但没有叉积),您可以在一个步骤中完成此操作 - 您将获得两个包含来自每个关系的分组记录的袋子。使用它来挑选最近的授权事件:

cogrp = COGROUP specificApiCall BY api_identifier, authEvents BY auth_identifier;
singleAuth = FOREACH cogrp 
    auth_sorted = ORDER authEvents BY auth_requestTime;
    auth_1 = LIMIT auth_sorted 1;
    GENERATE FLATTEN(specificApiCall), FLATTEN(auth_1);
    ;

然后FILTER 只留下 1 秒内的:

match = FILTER singleAuth BY (auth_requestTime-api_requestTime)<1000;

【讨论】:

谢谢 Winnie,我使用了 COGROUP,效果很好。你是最棒的!

以上是关于Pig Latin(在 foreach 循环中过滤第二个数据源)的主要内容,如果未能解决你的问题,请参考以下文章

我可以使用 Pig Latin 中的嵌套 FOREACH 语句生成嵌套包吗?

过滤 PIG LATIN 脚本中的列在为空的单元格上插入来自其他列的数据

如何优化 PIG latin 中的 group by 语句?

Store 命令中的 Pig Latin 参数

Pig Latin 在一个 FILTER 语句中使用两个数据源

通过在 PIG 中的同一块内计算的条件值在 FOREACH 块内进行过滤