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
不适用于在循环第一个关系时处理第二个关系。这是因为当您的关系中有一个包并且您想使用该包时,就好像它是它自己的关系一样。您不能同时使用apiRequests
和authEvents
,除非您先进行某种连接或分组,以将您需要的所有信息放入一个关系中。
如果您不需要将自己限制为单个授权事件,那么您的任务在概念上与 JOIN
和 FILTER
配合得很好:
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 语句?