如何从复杂的猪数据类型中提取简单的猪数据类型

时间:2014-04-29 18:54:06

标签: hadoop apache-pig

我正在尝试使用内置的BuildBloomBloom UDF在PIG中编写bloom过滤器构建器。调用BuildBloom UDF的语法是:

define bb BuildBloom('hash_type', 'vector_size', 'false_positive_rate');

其中向量大小和误报率参数作为charrarrays传入。由于我不必事先知道矢量大小,但在调用BuildBloom UDF之前它总是在脚本中可用,我想使用内置COUNT UDF而不是一些硬件编码值。类似的东西:

records = LOAD '$input' using PigStorage();
records = FOREACH records GENERATE 
    (long)     $0 AS value_fld:long, 
    (chararray)$1 AS filter_fld:chararray;
records_fltr = FILTER records by (filter_fld=='$filter_value') AND (value_fld is not null);
records_grp = GROUP records_fltr all;
records_count = FOREACH records_grp GENERATE (chararray) COUNT(records_fltr.value_fld) AS count:chararray;
n = FOREACH records_count GENERATE flatten(count);
define bb BuildBloom('jenkins', n, '$false_positive_rate');

问题在于,当我描述n时,我得到:n: {count: chararray}。可以预见,BuildBloom UDF调用失败,因为它将元组作为输入,它期望一个简单的chararray。我应该如何拉出chararray(即从COUNT强制转换为chararray)并将其分配给n以用于BuildBloom(...)的调用?

编辑:这是我尝试将N::count传递到BuildBloom(...) UDF时产生的错误。 describe N收益:N {count: chararray}。违规行(第40行)显示为:define bb BuildBloom('jenkins', N::count, '$fpr');

ERROR 1200: <file buildBloomFilter.pig, line 40, column 32>  mismatched input 'N::count' expecting set null

org.apache.pig.impl.logicalLayer.FrontendException: ERROR 1000: Error during parsing. <file buildBloomFilter.pig, line 40, column 32>  mismatched input 'N::count' expecting set null
    at org.apache.pig.PigServer$Graph.parseQuery(PigServer.java:1607)
    at org.apache.pig.PigServer$Graph.registerQuery(PigServer.java:1546)
    at org.apache.pig.PigServer.registerQuery(PigServer.java:516)
    at org.apache.pig.tools.grunt.GruntParser.processPig(GruntParser.java:991)
    at org.apache.pig.tools.pigscript.parser.PigScriptParser.parse(PigScriptParser.java:412)
    at org.apache.pig.tools.grunt.GruntParser.parseStopOnError(GruntParser.java:194)
    at org.apache.pig.tools.grunt.GruntParser.parseStopOnError(GruntParser.java:170)
    at org.apache.pig.tools.grunt.Grunt.exec(Grunt.java:84)
    at org.apache.pig.Main.run(Main.java:604)
    at org.apache.pig.Main.main(Main.java:157)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.hadoop.util.RunJar.main(RunJar.java:197)
Caused by: Failed to parse: <file buildBloomFilter.pig, line 40, column 32>  mismatched input 'N::count' expecting set null
    at org.apache.pig.parser.QueryParserDriver.parse(QueryParserDriver.java:235)
    at org.apache.pig.parser.QueryParserDriver.parse(QueryParserDriver.java:177)
    at org.apache.pig.PigServer$Graph.parseQuery(PigServer.java:1599)
    ... 14 more

2 个答案:

答案 0 :(得分:0)

在BuildBloom udf中,你发送“n”作为参数,它是元组。可能是“n :: columnname”会起作用。试试这个。

答案 1 :(得分:0)

如果您正在使用grunt shell,那么明显的方法是调用DUMP n;,等待作业完成运行,然后将值复制到define bloom...调用中。

这不是一个非常令人满意的答案,我猜。您很可能希望在脚本中运行此功能。这是一个非常黑客的方法。您需要3个文件:

  1. &#39; n_start.txt&#39;其中包含:

    n='
    
  2. &#39; n_end.txt&#39;其中包含单个字符:

    '
    
  3. &#39; bloom_build.pig&#39;其中包含:

    define bb BuildBloom('jenkins', '$n', '0.0001');
    
  4. 有了那些,你可以运行这个脚本:

    records = LOAD '$input' using PigStorage();
    records = FOREACH records GENERATE 
        (long)     $0 AS value_fld:long, 
        (chararray)$1 AS filter_fld:chararray;
    records_fltr = FILTER records by (filter_fld=='$filter_value') 
        AND (value_fld is not null);
    records_grp = GROUP records_fltr all;
    records_count = FOREACH records_grp GENERATE 
        (chararray) COUNT(records_fltr.value_fld) AS count:chararray;
    n = FOREACH records_count GENERATE flatten(count);
    
    --the new part
    STORE records_count INTO 'n' USING PigStorgae(',');
    --this will copy what you just stored into a local directory
    fs -copyToLocal n n
    --this will cat the two static files we created prior to running pig
    --with the count we just generated.  it will pass it through tr which will
    --strip out the newlines and then store it into a file called 'n.txt' which we
    --will use as a parameter file
    sh cat -s nstart.txt n/part-r-00000 nend.txt| tr -d '\n' > n.txt
    --RUN makes pig call one script within another.  Be forewarned that if pig returns 
    --a message with an error on a certain line, it is the line number of the expanded script
    RUN -param_file n.txt bloom_bulid.pig;
    

    在此之后,您可以像之前的预期一样致电bb。它很难看,而且可能更精通unix的人可能会删除n_start.txt和n_end.txt文件。

    另一个更清晰但更复杂的选项是编写一个新的UDF(如BuildBloom)扩展BuildBloomBase.java但有一个空构造函数,可以处理exec()方法中的所有内容。