在另一个关系上使用 FOREACH 时将关系传递给 PIG UDF?

Posted

技术标签:

【中文标题】在另一个关系上使用 FOREACH 时将关系传递给 PIG UDF?【英文标题】:Pass a relation to a PIG UDF when using FOREACH on another relation? 【发布时间】:2010-07-23 20:16:40 【问题描述】:

我们正在使用 Pig 0.6 来处理一些数据。我们数据的其中一列是以空格分隔的 id 列表(例如:35 521 225)。我们正在尝试将其中一个 id 映射到另一个包含 2 列映射的文件,例如(因此第 1 列是我们的数据,第 2 列是第 3 方数据):

35 6009 521 21599 225 51991 12 6129

我们编写了一个UDF,它接受列值(例如:“35 521 225”)和文件中的映射。然后,我们将拆分列值并遍历每个值,并从传入的映射中返回第一个映射值(认为这就是逻辑上的工作方式)。

我们正在像这样在 PIG 中加载数据:

data = LOAD 'input.txt' USING PigStorage() AS (name:chararray, category:chararray);

mappings = LOAD 'mappings.txt' USING PigStorage() AS (ourId:chararray, theirId:chararray);

那么我们的生成是:

output = FOREACH data GENERATE title, com.example.ourudf.Mapper(category, mappings);

但是我们得到的错误是: '解析时出错:[data::title: chararray,data::category, chararray] 中的别名映射无效`

Pig 似乎试图在我们的原始数据上找到一个名为“映射”的列。如果课程不存在的话。有没有办法传递加载到 UDF 中的关系?

PIG 中的“地图”类型在这方面有什么帮助吗?还是我们需要以某种方式加入这些价值观?

编辑:更具体地说 - 我们不想将所有类别 ID 映射到第 3 方 ID。我们只是想映射第一个。 UDF 将遍历我们的类别 ID 列表 - 并在找到第一个映射值时返回。所以如果输入看起来像:

一些产品\t35 521 225

输出将是: 一些产品\t6009

【问题讨论】:

【参考方案1】:

我不认为你可以在 Pig 中等待。

与您想要做的类似的解决方案是在 UDF 中加载映射文件,然后在 FOREACH 中处理每条记录。 PiggyBank LookupInFiles 中提供了一个示例。建议使用DistributedCache,而不是直接从DFS复制文件。

DEFINE MAP_PRODUCT com.example.ourudf.Mapper('hdfs://../mappings.txt');

data = LOAD 'input.txt' USING PigStorage() AS (name:chararray, category:chararray);

output = FOREACH data GENERATE title, MAP_PRODUCT(category);

如果您的映射文件不是太大,这将起作用。如果它不适合内存,您将不得不对映射文件进行分区并多次运行脚本,或者通过添加行号来调整映射文件的架构,并为每个产品使用原生 join 和嵌套 FOREACH ORDER BY/LIMIT 1 .

【讨论】:

以上是关于在另一个关系上使用 FOREACH 时将关系传递给 PIG UDF?的主要内容,如果未能解决你的问题,请参考以下文章

传递给 #or 的关系必须在结构上兼容。不兼容的值:[:references]

Rails - 传递给 #or 的关系必须在结构上兼容。不兼容的值:[:joins]

如何在 AWS Lambda 上创建 EC2 时将脚本传递给 UserData 字段?

Apache Pig - 在相同关系上嵌套 FOREACH

在 uicollectionview 上录制时将图像快速传递给详细视图控制器

在 Pig 中将关系传递给 Python UDF 时出错