単純なUDFを作成して、sparkのtemptablの時間フィールドからいくつかの値を変換または抽出しました。関数を登録しますが、sqlを使用して関数を呼び出すと、NullPointerExceptionがスローされます。以下は私の機能とそれを実行するプロセスです。ツェッペリンを使用しています。これは昨日うまくいっていたが、今朝は動かなくなった。
関数
def convert( time:String ) : String = {
val sdf = new Java.text.SimpleDateFormat("HH:mm")
val time1 = sdf.parse(time)
return sdf.format(time1)
}
関数を登録する
sqlContext.udf.register("convert",convert _)
SQLなしで関数をテストする-これは機能します
convert(12:12:12) -> returns 12:12
ZeppelinでSQLを使用して関数をテストすると、これは失敗します。
%sql
select convert(time) from temptable limit 10
誘惑の構造
root
|-- date: string (nullable = true)
|-- time: string (nullable = true)
|-- serverip: string (nullable = true)
|-- request: string (nullable = true)
|-- resource: string (nullable = true)
|-- protocol: integer (nullable = true)
|-- sourceip: string (nullable = true)
私が取得しているスタックトレースの一部。
Java.lang.NullPointerException
at org.Apache.hadoop.Hive.ql.exec.FunctionRegistry.getFunctionInfo(FunctionRegistry.Java:643)
at org.Apache.hadoop.Hive.ql.exec.FunctionRegistry.getFunctionInfo(FunctionRegistry.Java:652)
at org.Apache.spark.sql.Hive.HiveFunctionRegistry.lookupFunction(hiveUdfs.scala:54)
at org.Apache.spark.sql.Hive.HiveContext$$anon$3.org$Apache$spark$sql$catalyst$analysis$OverrideFunctionRegistry$$super$lookupFunction(HiveContext.scala:376)
at org.Apache.spark.sql.catalyst.analysis.OverrideFunctionRegistry$$anonfun$lookupFunction$2.apply(FunctionRegistry.scala:44)
at org.Apache.spark.sql.catalyst.analysis.OverrideFunctionRegistry$$anonfun$lookupFunction$2.apply(FunctionRegistry.scala:44)
at scala.Option.getOrElse(Option.scala:120)
at org.Apache.spark.sql.catalyst.analysis.OverrideFunctionRegistry$class.lookupFunction(FunctionRegistry.scala:44)
関数を直接定義する代わりにudfを使用する
import org.Apache.spark.sql.functions._
val convert = udf[String, String](time => {
val sdf = new Java.text.SimpleDateFormat("HH:mm")
val time1 = sdf.parse(time)
sdf.format(time1)
}
)
Udfの入力パラメーターは、列(または列)です。そして、戻り値の型は列です。
case class UserDefinedFunction protected[sql] (
f: AnyRef,
dataType: DataType,
inputTypes: Option[Seq[DataType]]) {
def apply(exprs: Column*): Column = {
Column(ScalaUDF(f, dataType, exprs.map(_.expr), inputTypes.getOrElse(Nil)))
}
}
関数をUDFとして定義する必要があります。
import org.Apache.spark.sql.expressions.UserDefinedFunction
import org.Apache.spark.sql.functions.udf
val convertUDF: UserDefinedFunction = udf((time:String) => {
val sdf = new Java.text.SimpleDateFormat("HH:mm")
val time1 = sdf.parse(time)
sdf.format(time1)
})
次に、UDFをDataFrameに適用します。
// assuming your DataFrame is already defined
dataFrame.withColumn("time", convertUDF(col("time"))) // using the same name replaces existing
さて、実際の問題に関しては、このエラーを受け取る1つの理由は、DataFrameにnullである行が含まれていることが原因である可能性があります。 UDFを適用する前にそれらを除外すると、問題なく続行できるはずです。
dataFrame.filter(col("time").isNotNull)
Nullに遭遇する以外にUDFを実行するときにNullPointerExceptionが発生する原因は何でしょうか。私の提案とは異なる理由が見つかった場合は、喜んでお知らせします。