将多个参数传递给 Pig Filter UDF
Posted
技术标签:
【中文标题】将多个参数传递给 Pig Filter UDF【英文标题】:Pass mutiple parameters to Pig Filter UDF 【发布时间】:2015-12-06 07:09:33 【问题描述】:我是 Pig 脚本的新手。
我想将多个参数传递给 Pig 过滤器 UDF,但出现错误“标量投影无效:需要从关系中投影一列才能用作标量”
我正在执行以下步骤。
input = load '....';
dump input; /* working able to see data*/
output = FILTER input by not FilterUDF(input,val1,val2);
这没有奏效。所以我尝试了以下。
input = load '......';
dump input; /* working able to see data*/
dataWithVal = FOREACH input GENERATE $0,$1,val1,val2;
dump dataWithVal; /* working able to see data with values*/
output = FILTER dataWithVal by not FilterUDF(dataWithVal);
这也没有用。所以我将我的值添加到一个文件中,将该文件复制到 HDFS 中,然后将其与输入数据交叉连接,但仍然出现相同的错误。
input = load '........';
dump input; /* working able to see data*/
val = load '........';
dump val; /* working able to values*/
interData = cross input, val;
dump interData; /* working able to see cross joined data*/
output = FILTER interData by not FilterUDF(interData);
对于上述所有选项,我得到的错误与“无效的标量投影:需要从关系中投影一列才能用作标量。”
对于第一种情况,我的FilterUDF结构如下。
import org.apache.pig.FilterFunc;
import java.io.IOException;
import org.apache.pig.data.Tuple;
public class FilterUDF extends FilterFunc
public boolean exec(Tuple input, int val, String Val) throws IOException
/*some code here*/
尝试了一种替代方法但没有奏效。
import org.apache.pig.FilterFunc;
import java.io.IOException;
import org.apache.pig.data.Tuple;
public class FilterUDF extends FilterFunc
private Tuple input;
private int Ival;
private String Sval;
public FilterUDF(Tuple input, int Ival, String Sval)
this.input = input;
this.Ival = Ival;
this.Sval = Sval;
public Boolean exec(Tuple arg0) throws IOException
/*Some code*/
对于情况二和三,我的FilterUDF结构如下。
import org.apache.pig.FilterFunc;
import java.io.IOException;
import org.apache.pig.data.Tuple;
public class FilterUDF extends FilterFunc
public Boolean exec(Tuple input) throws IOException
/*some code here*/
我做错了什么? 如何将多个参数传递给 Pig UDF? “无效标量投影”错误背后的原因是什么?
在此先感谢您的帮助。
【问题讨论】:
【参考方案1】:我不确定您要使用 UDF 计算什么,因为您的问题描述有点模糊,但在您的所有三个代码示例中,您都试图将关系传递给您的 UDF,而这并没有真正有意义(输入、dataWithVal 和 interData 是关系)。您需要传递它值。因此,假设您使用 UDF 断言 val1 和 val2 相同(或其他),那么您可以编写
input = LOAD '...'; /* load some data */
output = FILTER input BY FilterUDF(val1, val2);
你的 UDF 看起来像
import org.apache.pig.FilterFunc;
import java.io.IOException;
import org.apache.pig.data.Tuple;
public class FilterUDF extends FilterFunc
public Boolean exec(Tuple input) throws IOException
if (input == null || input.size() == 0)
return null;
int val1 = input.get(0) // gets val1 from pig
int val2 = input.get(1) // gets val2 from pig
/*rest of code*/
如您所见,您可以向 UDF 传递任意数量的参数;这就是org.apache.pig.data.Tuple
的用途;只需根据需要传递尽可能多的参数,然后在 UDF 中使用 .get(i)
解析它们
【讨论】:
非常感谢 GoBrewers14 的回复。我想要实现的是,我想根据关系中的一些值过滤数据。例如,我只想要工资低于 10000 的部门 10 的员工。emp = load '/emp.csv' using PigStorage(',') as (name,dept); filteremp = FILTER emp by FilterUDF(emp,10,1000);
和在 UDF 中,我计划使用 get(1) 从 emp 关系中提取部门,然后应用我的逻辑。可能还有其他方法可以实现这一目标,但我想遵循这个。
1)。您正在使这种 方式 比使用 UDF 更复杂。 2)。当没有名为salary
的列时,如何过滤salary
?
抱歉,加载数据时忘记添加薪水栏。 emp = load '/emp.csv' using PigStorage(',') as (name,dept,salary); filteremp = FILTER emp by FilterUDF(emp,10,1000);
然后 get(1) 代表部门,get(2) 代表工资。它会起作用吗?我究竟做错了什么?我也想按照同样的方式,那我要对现有代码做哪些改动呢?以上是关于将多个参数传递给 Pig Filter UDF的主要内容,如果未能解决你的问题,请参考以下文章