假设我想制作一个Spark UDF来反转结构数组的排序。结构的具体类型应该无关紧要,所以我尝试了:
val reverseUDF = udf((s:Seq[_]) => s.reverse)
但是这给了
java.lang.UnsupportedOperationException: Schema for type Any is not supported
我还尝试使用泛型方法和强制类型泛型类型参数作为Product
的子类型:
def reverse[T <: Product](s:Seq[T]) = {
s.reverse
}
val reverseUDF = udf(reverse _)
这给出了:
scala.MatchError: Nothing (of class scala.reflect.internal.Types$TypeRef$$anon$6)
这甚至可能吗?
答案 0 :(得分:2)
不是。 Spark必须知道返回输出类型,并且无法使用SQL表达式来确定它。您必须为要使用的每种类型定义特定的udf
,例如:
udf(reverse[(String, Int)] _)
udf(reverse[(String, Long, String)] _)
等等。但是在实践中这些都没有用,因为你永远不会在你的udf中看到Product
类型。结构类型始终编码为Row
- Spark Sql UDF with complex input parameter。
如果您使用Spark 2.3,您可以将任意reverse
表示为:
import org.apache.spark.sql.Row
import org.apache.spark.sql.types.DataType
def reverse(schema: DataType) = udf(
(xs: Seq[Row]) => xs.map(x => Row.fromSeq(x.toSeq.reverse)),
schema
)
但您必须为每个实例提供架构: