【问题标题】:Pig - passing Databag to UDF constructorPig - 将 Databag 传递给 UDF 构造函数
【发布时间】:2013-12-19 12:58:42
【问题描述】:

我有一个脚本正在加载有关场地的一些数据:

venues = LOAD 'venues_extended_2.csv' USING org.apache.pig.piggybank.storage.CSVLoader() AS (Name:chararray, Type:chararray, Latitude:double, Longitude:double, City:chararray, Country:chararray);

然后我想创建一个 UDF,它有一个接受场地类型的构造函数。

所以我尝试这样定义这个 UDF:

DEFINE GenerateVenues org.gla.anton.udf.main.GenerateVenues(venues);

这是实际的 UDF:

public class GenerateVenues extends EvalFunc<Tuple> {

    TupleFactory mTupleFactory = TupleFactory.getInstance();
    BagFactory mBagFactory = BagFactory.getInstance();

    private static final String ALLCHARS = "(.*)";
    private ArrayList<String> venues;

    private String regex;

    public GenerateVenues(DataBag venuesBag) {
        Iterator<Tuple> it = venuesBag.iterator();
        venues = new ArrayList<String>((int) (venuesBag.size() + 1)); // possible fails!!!
        String current = "";
        regex = "";
        while (it.hasNext()){
            Tuple t = it.next();
            try {
                current = "(" + ALLCHARS + t.get(0) + ALLCHARS + ")";
                venues.add((String) t.get(0));
            } catch (ExecException e) {
                throw new IllegalArgumentException("VenuesRegex: requires tuple with at least one value");
            }
            regex += current + (it.hasNext() ? "|" : "");
        }
    }

    @Override
    public Tuple exec(Tuple tuple) throws IOException {
        // expect one string
        if (tuple == null || tuple.size() != 2) {
            throw new IllegalArgumentException(
                    "BagTupleExampleUDF: requires two input parameters.");
        }
        try {
            String tweet = (String) tuple.get(0);
            for (String venue: venues)
            {
                if (tweet.matches(ALLCHARS + venue + ALLCHARS))
                {
                    Tuple output = mTupleFactory.newTuple(Collections.singletonList(venue));
                    return output;
                }
            }
            return null;
        } catch (Exception e) {
            throw new IOException(
                    "BagTupleExampleUDF: caught exception processing input.", e);
        }
    }
}

当脚本执行时,在DEFINE 部分就在(venues); 之前触发错误:

2013-12-19 04:28:06,072 [main] ERROR org.apache.pig.tools.grunt.Grunt - ERROR 1200: <file script.pig, line 6, column 60>  mismatched input 'venues' expecting RIGHT_PAREN

显然我做错了什么,你能帮我找出问题所在吗? 是 UDF 不能接受场所关系作为参数吗?或者这种关系不是由DataBag 表示的public GenerateVenues(DataBag venuesBag)? 谢谢!

PS 我使用的是 Pig 版本 0.11.1.1.3.0.0-107

【问题讨论】:

    标签: apache-pig user-defined-functions


    【解决方案1】:

    正如@WinnieNicklaus 已经说过的,您可以将字符串传递给 UDF 构造函数。

    话虽如此,您的问题的解决方案是使用分布式缓存,您需要覆盖 public List&lt;String&gt; getCacheFiles() 以返回将通过分布式缓存提供的文件名列表。这样,您就可以将该文件作为本地文件读取并构建您的表。

    缺点是Pig没有初始化函数,所以你必须实现类似的东西

    private void init() {
        if (!this.initialized) {
            // read table
        }
    }
    

    然后从exec 调用它作为第一件事。

    【讨论】:

      【解决方案2】:

      您不能将关系用作 UDF 构造函数中的参数。只有字符串可以作为参数传递,如果它们确实是另一种类型,则必须在构造函数中将它们解析出来。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-07
        • 2011-09-24
        • 2012-01-15
        • 1970-01-01
        相关资源
        最近更新 更多