我在pig中有以下代码,其中我正在检查存储在记录中的主文件中的字段(记录中的srcgt& destgt),如另一个文件(intlgt.txt)中提到的值338,918299,181,238
但是如下所述,它会抛出错误。你能否建议如何在Apache Pig版本0.15.0(r1682971)上克服这个问题。
猪代码:
record = LOAD '/u02/20160201*.SMS' USING PigStorage('|','-tagFile') ;
intlgtrec = LOAD '/u02/config/intlgt.txt' ;
intlgt = foreach intlgtrec generate $0 as intlgt;
cdrfilter = foreach record generate (chararray) $1 as aparty, (chararray) $2 as bparty,(chararray) $3 as dt,(chararray)$4 as timestamp,(chararray) $29 as status,(chararray) $26 as srcgt,(chararray) $27 as destgt,(chararray)$0 as cdrfname ,(chararray) $13 as prepost;
intlcdrs = FILTER cdrfilter by ( STARTSWITH(srcgt,intlgt::intlgt) or STARTSWITH(destgt,intlgt::intlgt) ) ;`
错误是:
WARN org.apache.hadoop.mapred.LocalJobRunner - job_local1939982195_0002
java.lang.Exception: org.apache.pig.backend.executionengine.ExecException: ERROR 0: Scalar has more than one row in the output. 1st : (338), 2nd :(918299) (common cause: "JOIN" then "FOREACH ... GENERATE foo.bar" should be "foo::bar") at org.apache.hadoop.mapred.LocalJobRunner$Job.runTasks(LocalJobRunner.java:462) at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:522)
答案 0 :(得分:0)
使用时
intlcdrs = FILTER cdrfilter by ( STARTSWITH(srcgt,intlgt::intlgt) or STARTSWITH(destgt,intlgt::intlgt) );
PIG正在寻找一个标量。无论是数字,还是chararray;但是一个人。所以猪假设你的intlgt :: intlgt是一行的关系。例如
的结果intlgt = foreach (group intlgtrec all) generate COUNT_STAR(intlgtrec.$0)
(这会生成单行,原始关系中的记录数)
在您的情况下,intlgt包含多行,因为您尚未对其进行任何分组。 根据您的代码,您正在尝试查找两端都有intlgt的SMS消息。可能的解决方案:
如果您的intlgt enteries都具有相同的长度(例如3),则生成substring(srcgt,1,3)作为srcgtshort,并使用record :: srcgtshort JOIN intlgt :: intlgt。这将为您提供srcgt以intlgt中的值开头的记录。然后对destgt重复此操作。
如果它们的长度很少(例如,某些条目的长度为3,有些条目长度为4,有些条目的长度为5),则可以执行相同的操作,但这样会更费力(作为字段每个'长度'都需要。)
如果两个关系中的行数不是太大,则在它们之间进行交叉,这将创建记录中的行和来自intlgt的行的所有可能组合。然后你可以通过STARTSWITH(srcgt,intlgt :: intlgt)进行过滤,因为它们中的两个是相同关系的字段。谨防这种方法,因为记录的数量可以变得巨大!