【问题标题】:PIG (v0.10.0) excepttion during FILTER operation: java.lang.Integer cannot be cast to java.lang.StringFILTER 操作期间的 PIG (v0.10.0) 异常:java.lang.Integer 无法转换为 java.lang.String
【发布时间】:2013-03-13 19:03:36
【问题描述】:

这是我的(看似微不足道的)PIG 脚本,后面是它生成的异常:

raw_logs = LOAD './Apache-WebLog-Samples.d/access_log.txt' USING TextLoader() AS (line:chararray);

logs = FOREACH raw_logs GENERATE FLATTEN (
    REGEX_EXTRACT_ALL(line, '^(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+\\[([\\w:/]+\\s[+\\-]\\d{4})\\]\\s+"(..*)"\\s+(\\S+)\\s+(\\S+)'))
       AS (remoteAddr:    chararray,
           remoteLogname: chararray,
           user:          chararray,
           date_time:     chararray, 
           request:       chararray,
           httpStatus:          int, <- Here's the problem. But goes away when I set to chararray.
           numBytes:            int);

httpGET200 = FILTER logs BY (request MATCHES '^GET\\s.*') AND (httpStatus == 200);

mylimit = LIMIT httpGET200 40;

DUMP mylimit;

猪脚本

java.lang.Exception: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:404)
Caused by: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

[ ... non meaningful error output removed ... ]

2013-03-13 14:04:10,882 [main] INFO  org.apache.pig.tools.pigstats.SimplePigStats - Script Statistics: 

HadoopVersion   PigVersion  UserId  StartedAt   FinishedAt  Features
2.0.0-cdh4.2.0  0.10.0-cdh4.2.0 nmvega  2013-03-13 14:04:05 2013-03-13 14:04:10 FILTER,LIMIT

Failed!    
Failed Jobs:
JobId   Alias   Feature Message Outputs
job_local1982169921_0001    httpGET200,logs,mylimit,raw_logs        Message: Job failed!    

Input(s):
Failed to read data from "file:///home/user/Dropbox/CodeDEV.d/BIG-DATA-SNIPPETS.d/PIG.d/Apache-WebLog-Samples.d/access_log.txt"

Output(s):

异常消息

除了 'httpGET200' 关系外,一切正常。由于对我来说不明显的原因,“httpStatus == 200”子句导致了上述异常。当我删除该条款时,问题就消失了。或者,或者,当我更改架构并将“httpStatus”声明为“chararray”类型而不是“int”类型时(如上所述并且适用于 HTTP 状态代码),问题也消失了......(当然,当我这样做时,我必须编辑关系以插入引号,如下所示:httpStatus == '200')。

我检查了输入数据文件并验证,对于每一行,与“httpStatus”对应的字段确实总是一个整数(……嗯,一个表示整数的子字符串)。

顺便说一下,这里是 grunt 报告的模式(即预期的):

grunt> describe httpGET200;
httpGET200: {remoteAddr: chararray,remoteLogname: chararray,user: chararray,date_time: chararray,request: chararray,httpStatus: int,numBytes: int}

我想了解这里发生了什么(我的误解或 PIG 限制)。有人能解释一下吗?

谢谢!

【问题讨论】:

  • 我建议转储您的日志关系,以确保您的正则表达式按您的预期提取 http 状态。我怀疑它与您期望的响应代码不匹配。
  • 谢谢种子头。实际上这是我做的第一件事(即转储日志)。正则表达式完全按照设计提取所有内容(即每行输入都按预期工作)。

标签: exception hadoop mapreduce apache-pig


【解决方案1】:

在我看来,如果 REGEX_EXTRACT_ALL 将输出模式中的字段设置为 int 将在稍后对该字段执行算术运算时导致 ClassCastException。可能是因为所有字段都保留下来,并且在返回的元组中被视为 chararray,尽管给定了模式。

作为一种解决方法,您可以将 所有字段 设置为 chararray,然后执行显式转换 (conv):

logs = FOREACH raw_logs ....
conv = FOREACH logs generate remoteAddr, remoteLogname, user, date_time, 
         request, (int)httpStatus, (int)numBytes;

然后你可以应用你最初使用的过滤器:

httpGET200 = FILTER conv BY (request MATCHES '^GET\\s.*') AND (httpStatus == 200);

您可以在thisticket 中找到有关类似问题的更多信息:

【讨论】:

  • 洛兰德,谢谢。那张票的问题确实是我的问题。套用它:在 PIG 中,简单地声明一个 STRING 是一个 INT,不足以将它变成一个 INT。再次强调解决方案:使用“REGEX_EXTRACT_ALL”时,只需将所有字段设置为“chararray”,然后执行额外的强制转换步骤,如上所示。
  • 是的,这就是我的建议。在这个问题上您需要更多帮助吗?
  • 我刚遇到这个问题,我只想说声谢谢。这是猪最可笑的问题。
【解决方案2】:

我在尝试比较 Pig 脚本中 FILTER 语句中的两个整数时遇到了同样的问题。 我发现最优雅的解决方案是使用GenericInvoker。 所以对于你的问题,我会使用:

--StringToInt would be func that will invoke valueOf method of Integer class for String arg.
DEFINE StringToInt InvokeForInt('java.lang.Integer.valueOf', 'String');


--Now we can use it in our FILTER statement (without need to make projections in order to get right types schema for your tuples)
httpGET200=FILTER logs BY (request MATCHES '^GET\\s.*') AND StringToInt(httpStatus)== 200;

瞧!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    相关资源
    最近更新 更多