从MS SQL数据库导入数据时,可能存在空值。在Spark中,DataFrames能够处理空值。但是当我尝试将DataFrame转换为强类型数据集时,我收到编码器错误。
这是一个简单的例子:
case class optionTest(var a: Option[Int], var b: Option[Int])
object testObject {
def main(args: Array[String]): Unit = {
import spark.implicits._
val df = spark.sparkContext.parallelize(Seq(input)).toDF()
val df2 = Seq((1, 3), (3, Option(null)))
.toDF("a", "b")
.as[optionTest]
df2.show()
}
}
以下是此案例的错误:
No Encoder found for Any
- field (class: "java.lang.Object", name: "_2")
- root class: "scala.Tuple2"
java.lang.UnsupportedOperationException: No Encoder found for Any
- field (class: "java.lang.Object", name: "_2")
- root class: "scala.Tuple2"
从DataFrame创建数据集时,建议处理可为空值的方法是什么?
答案 0 :(得分:1)
问题是您的Dataframe与您的案例类不匹配。
您的第一对是(Int, Int)
,第二对是(Int, Option[Null])
。
要注意的一件事是,如果您想要代表Option[Int]
,则该值将为Some(3)
,例如,或None
表示缺席值。
需要注意的棘手问题是,Scala Int
是AnyVal
的子类,而可编写的引用(在您编写的Scala代码中几乎不存在)位于AnyRef
Scala对象层次结构的一面。
因为你有大量的对象遍布Scala对象模型,所以Spark必须将你的数据视为Any
,即所有内容的超类。没有可以处理的编码器。
所有这些说明,您的数据必须如下所示:
val df2 = Seq((Some(1), Some(3)), (Some(3), None))
作为旁注,您的案例类应如下所示:
case class OptionTest(a: Option[Int], b: Option[Int])
答案 1 :(得分:0)
如果您想使用Option
,则必须将其用于所有记录。您还应该使用None
代替Option(null)
:
Seq((1, Some(3)), (3, None)).toDF("a", "b").as[optionTest]