2

これが私の(一見些細な)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」を「int」ではなく「chararray」型に宣言すると (上記のように、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 の制限のいずれか)。誰でも光を当てることができますか?

ありがとうございました!

4

2 に答える 2

5

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);

このチケットで、同様の問題に関する詳細情報を見つけることができます。

于 2013-03-13T23:15:24.520 に答える
1

Pig スクリプトの FILTER ステートメントで 2 つの整数を比較しようとすると、同じ問題が発生しました。私が見つけた最も洗練された解決策は、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;

出来上がり!

于 2014-08-27T15:24:42.273 に答える