Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala SparkSQL创建UDF以处理列可以是有时结构和有时字符串时的异常_Scala_Apache Spark_Apache Spark Sql - Fatal编程技术网

Scala SparkSQL创建UDF以处理列可以是有时结构和有时字符串时的异常

Scala SparkSQL创建UDF以处理列可以是有时结构和有时字符串时的异常,scala,apache-spark,apache-spark-sql,Scala,Apache Spark,Apache Spark Sql,我正在努力创建一个udf来提取一些列数据。列很复杂,因为有时它是字符串,但在许多情况下可以是struct。我只想考虑列为struct时的时间,并提取它所需的信息 假设这个例子: SELECT annoyingCol.data From SomeDf 烦恼col.data等于string或struct,以避免出现如下错误:需要struct type,但得到string。我想知道是否可以创建一个检查列类型的自定义项,例如: SELECT case when isStruct(annoyingC

我正在努力创建一个udf来提取一些列数据。列很复杂,因为有时它是字符串,但在许多情况下可以是struct。我只想考虑列为struct时的时间,并提取它所需的信息

假设这个例子:

SELECT annoyingCol.data From SomeDf
烦恼col.data等于string或struct,以避免出现如下错误:
需要struct type,但得到string。我想知道是否可以创建一个检查列类型的自定义项,例如:

SELECT
  case when isStruct(annoyingCol.data) then annoyingCol.data.my_data else null end
FROM SomeDf
我试过这个

val isStruct = udf((r: Row) => {
    import org.apache.spark.sql.Row
    import org.apache.spark.sql.types.BooleanType
    import scala.util.Try
    Try(r.getAs[String]("estimation_data_inc_waypoints")).isSuccess
  }
)
spark.udf.register("isStruct", isStruct)

但是失败了,我知道我错过了一些东西。任何帮助都将不胜感激。

从技术上讲,您可以创建如下
udf

val isStruct = udf((r: Any) => r match {
  case _: Row => true
  case _ => false
})

val df = Seq(("foo", (1, "bar"))).toDF


df.select(isStruct($"_1")).show
// +-------+
// |UDF(_1)|
// +-------+
// |  false|
// +-------+


df.select(isStruct($"_2")).show
// +-------+
// |UDF(_2)|
// +-------+
// |   true|
// +-------+
但是

列很复杂,因为有时它是字符串,但在许多情况下可以是struct

听起来不对,因为DataFrame不能包含异构列,并且

需要结构类型,但得到字符串

是规划器错误,即使
udf
的类型与数据不匹配,也不会引发此错误。相反,您将得到类似以下内容的运行时
ClassCastException

Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to org.apache.spark.sql.Row
所以你的问题在别的地方。可能在这里:

annoyingCol.data
如果输入的结构不好,并且
hatteringcol
有时被推断为
StringType
,则点语法将不起作用,您将得到问题中的查询计划器异常

这应该在查询之外处理。您可以检查以下类型:

 df.schema("annoyingCol").dataType match {
   case _: StructType =>  ??? // Take some path
   case _             =>  ??? // Take another path
 }
或者可以


如果可以的话,我强烈建议您在源代码处或在Spark中将数据解析为
DataFrame
之前,在上游解决此问题。

您的意思是不同的DataFrame(具有相同的列名)的列类型不同吗?不,Dataframe是相同的,但模式可能会更改json数组并不严格,在某些情况下可能会更改,因此每一行可能略有不同。Spark在了解json模式是什么时做得很好,但由于它只是对行进行采样,Spark可能会错过json结构不同的一些情况。
 if (hasColumn(df, "annoyingCol.data") {
   ??? // Take some path
 } else {
   ??? // Take another path
 }