4

スパーク2データセットヌル値例外

入力CSV Dataset.filterスパークにおけるこのヌルエラーの取得:

name,age,stat 
abc,22,m 
xyz,,s 

操作コード:(

case class Person(name: String, age: Long, stat: String) 

val peopleDS = spark.read.option("inferSchema","true") 
    .option("header", "true").option("delimiter", ",") 
    .csv("./people.csv").as[Person] 
peopleDS.show() 
peopleDS.createOrReplaceTempView("people") 
spark.sql("select * from people where age > 30").show() 

失敗コードを追加次の行が返さエラー):

val filteredDS = peopleDS.filter(_.age > 30) 
filteredDS.show() 
のは、ステップ・バイ・ステップ手放すが、すべてを説明する必要があり、あなたが得る

戻り値はnullエラー

java.lang.RuntimeException: Null value appeared in non-nullable field: 
- field (class: "scala.Long", name: "age") 
- root class: "com.gcp.model.Person" 
If the schema is inferred from a Scala tuple/case class, or a Java bean, please try to use scala.Option[_] or other nullable types (e.g. java.lang.Integer instead of int/scala.Int). 

答えて

9

例外:

csvデータソースを使用して、負荷データはすべてのフィールドが nullableとしてマークされている
  • val path: String = ??? 
    
    val peopleDF = spark.read 
        .option("inferSchema","true") 
        .option("header", "true") 
        .option("delimiter", ",") 
        .csv(path) 
    
    peopleDF.printSchema 
    
    root 
    |-- name: string (nullable = true) 
    |-- age: integer (nullable = true) 
    |-- stat: string (nullable = true) 
    
  • ミッシングフィールドは、Dataset[Row]ageフィールドをエンコードするためにLongを使用するDataset[Person]に変換

    peopleDF.where($"age".isNull).show 
    
    +----+----+----+ 
    |name| age|stat| 
    +----+----+----+ 
    | xyz|null| s| 
    +----+----+----+ 
    
  • SQL NULLとして表現されます。 ScalaのLongnullにできません。入力スキーマがnullableあるので、出力スキーマは、そののにもかかわらず、nullableまま:それはas[T]ですべてのスキーマには影響を与えません

    val peopleDS = peopleDF.as[Person] 
    
    peopleDS.printSchema 
    
    root 
    |-- name: string (nullable = true) 
    |-- age: integer (nullable = true) 
    |-- stat: string (nullable = true) 
    

    注こと。

  • DatasetをSQL(登録済みテーブル)またはDataFrame APIを使用してクエリすると、Sparkはオブジェクトを逆シリアル化しません。スキーマはまだnullableですので、我々は実行することができます。

    peopleDS.where($"age" > 30).show 
    
    +----+---+----+ 
    |name|age|stat| 
    +----+---+----+ 
    +----+---+----+ 
    

    何の問題もなく。これは単純なSQLロジックであり、NULLは有効な値です。

  • 我々は静的にDataset APIを入力した使用:

    peopleDS.filter(_.age > 30) 
    

    スパークは、オブジェクトをデシリアライズする必要があります。 Longnull(SQL NULL)になることはできません。

    NPEを取得していない場合は、あなたは、パターンマッチングを使用することができます希望する場合

    peopleDS.filter(_.age.map(_ > 30).getOrElse(false)) 
    
    +----+---+----+ 
    |name|age|stat| 
    +----+---+----+ 
    +----+---+----+ 
    

    :調整フィルタ機能を

    case class Person(name: String, age: Option[Long], stat: String) 
    

    :あなたのデータの

  • 正しい静的型付け表現はOptionalタイプを使用する必要があります

    peopleDS.filter { 
        case Some(age) => age > 30 
        case _   => false  // or case None => false 
    } 
    

    namestatのオプションの型を使用する必要はありませんが、とにかくお勧めします。 Scala StringはちょうどJavaのStringなので、nullとすることができます。もちろん、この方法を使用する場合は、アクセスされた値がnullかどうかを明示的にチェックする必要があります。 Spark 2.0 Dataset vs DataFrame

    関連