Apache spark case类的Spark模式具有正确的空性

Apache spark case类的Spark模式具有正确的空性,apache-spark,apache-spark-sql,apache-spark-ml,apache-spark-dataset,spark-csv,Apache Spark,Apache Spark Sql,Apache Spark Ml,Apache Spark Dataset,Spark Csv,对于自定义估计器的transformSchema方法,我需要能够将输入数据帧的模式与case类中定义的模式进行比较。通常情况下,可按如下所述执行。但是,使用了错误的可空性: spark.read.csv()作为[MyClass]推断出的df的实际模式可能如下所示: root |-- CUSTOMER_ID: integer (nullable = false) 和案例类: case class MySchema(CUSTOMER_ID: Int) 要进行比较,我使用: val rawSch

对于自定义估计器的transformSchema方法,我需要能够将输入数据帧的模式与case类中定义的模式进行比较。通常情况下,可按如下所述执行。但是,使用了错误的可空性:

spark.read.csv()作为[MyClass]
推断出的df的实际模式可能如下所示:

root
 |-- CUSTOMER_ID: integer (nullable = false)
和案例类:

case class MySchema(CUSTOMER_ID: Int)
要进行比较,我使用:

val rawSchema = ScalaReflection.schemaFor[MySchema].dataType.asInstanceOf[StructType]
  if (!rawSchema.equals(rawDf.schema))
不幸的是,这总是会产生
false
,因为从case类手动推断的新模式将null设置为
true
(因为ja java.Integer实际上可能为null)


在创建模式时,如何指定
nullable=false

可以说,您正在混合不属于同一空间的内容。ML管道本质上是动态的,引入静态类型的对象并不能真正改变这一点

此外,定义为以下类型的类的架构:

案例类MySchema(客户ID:Int)
将没有可为空的
客户ID
scala.Int
java.lang.Integer
不同:

scala>import org.apache.spark.sql.catalyst.ScalaReflection.schemaFor
导入org.apache.spark.sql.catalyst.ScalaReflection.schemaFor
scala>案例类MySchema(客户ID:Int)
定义类MySchema
scala>schemaFor[MySchema]。数据类型
res0:org.apache.spark.sql.types.DataType=StructType(StructField(CUSTOMER\u ID,IntegerType,false))
也就是说,如果您想要
可为空
字段
选项[Int]

案例类MySchema(客户ID:Option[Int])
如果不希望为空,请使用上述
Int

这里的另一个问题是,对于
csv
,根据定义,每个字段都可以为空,并且该状态由编码的
数据集
“继承”。因此,在实践中:

spark.read.csv(...)
将始终导致:

根目录
|--客户标识:整数(nullable=true)
这就是为什么会出现模式不匹配。不幸的是,对于不强制可空性约束的源,例如
csv
json
,不可能重写
nullable
字段

如果没有可为空的架构是一项困难的要求,您可以尝试:

spark.createDataFrame(
spark.read.csv(…).rdd,
schemaFor[MySchema].dataType.asInstanceOf[StructType]
).as[MySchema]
只有当您知道数据实际上是免费的时,这种方法才有效。任何
null
值都会导致运行时异常

spark.read.csv(...)