在Spark 2.0中,我发现在Scala中创建UDT的one example似乎不再适用。 UserDefinedType类已设置为private
,评论为:
注意:这是以前在Spark 1.x中的开发人员API。我们在Spark 2.0中将其设为私有,因为我们很可能会创建一个与数据集一起使用的新版本。
UDTRegistration的意图可能是声明UDT的新机制,但它也是private
。
到目前为止,我的研究告诉我,没有办法在Spark 2.0中声明自己的UDT;这个结论是否正确?
答案 0 :(得分:3)
你现在是对的,Spark 2.x已经没有任何类型的UDT可以用作Spark 1.x中的API。
您可以在此故障单SPARK-14155中看到,他们让它成为创建新API的助手。我们希望将在Spark 2.2 SPARK-7768中关闭自Spark 1.5以来打开的票证。
嗯,类型现在不适合创建你的UDT但是......你可以将自定义对象设置为DataSet的技巧很少。 Here就是一个例子。
答案 1 :(得分:0)
您可以使用UDTRegistration使UDT与Spark一起使用。 这是一种实现方法:
说您要使用多态记录:
trait CustomPoly
case class FooPoly(id:Int) extends CustomPoly
case class BarPoly(value:String, secondValue:Long) extends CustomPoly
polySeq.filter(_.poly match {
case FooPoly(value) => value == 1
case _ => false
}).show()
您可以编写一个自定义的UDT,将所有内容编码为字节(我在这里使用Java序列化,但是最好检测Spark的Kryo上下文)。
首先定义UDT类:
class CustomPolyUDT extends UserDefinedType[CustomPoly] {
val kryo = new Kryo()
override def sqlType: DataType = org.apache.spark.sql.types.BinaryType
override def serialize(obj: CustomPoly): Any = {
val bos = new ByteArrayOutputStream()
val oos = new ObjectOutputStream(bos)
oos.writeObject(obj)
bos.toByteArray
}
override def deserialize(datum: Any): CustomPoly = {
val bis = new ByteArrayInputStream(datum.asInstanceOf[Array[Byte]])
val ois = new ObjectInputStream(bis)
val obj = ois.readObject()
obj.asInstanceOf[CustomPoly]
}
override def userClass: Class[CustomPoly] = classOf[CustomPoly]
}
然后注册:
// NOTE: The file you do this in has to be inside of the org.apache.spark package!
UDTRegistration.register(classOf[CustomPoly].getName, classOf[CustomPolyUDT].getName)
那么您就可以使用它!
// As shown above:
case class UsingPoly(id:Int, poly:CustomPoly)
Seq(
UsingPoly(1, new FooPoly(1)),
UsingPoly(2, new BarPoly("Blah", 123)),
UsingPoly(3, new FooPoly(1))
).toDS
polySeq.filter(_.poly match {
case FooPoly(value) => value == 1
case _ => false
}).show()
在这里查看我的原始帖子,其中还有一个示例: How to store custom objects in Dataset?