Apache spark spark sql和dataframes中控制字段的可空性
我正在使用spark sql的DataFrame实现一个通用的数据集成组件。 基本思想是,用户通过命名字段并使用简单的sql片段(可以出现在select子句中的片段)映射字段来配置字段,组件添加这些列并将它们分组到结构字段中(使用DSL列) 稍后的处理将这些结构字段中的一些字段分组到一个数组中,此时我遇到了一个问题,即其中一个字段在一个元组中可为null,而在另一个元组中不可为null 由于字段分组在一个结构中,所以我能够提取结构类型,修改它并使用Column.cast方法将其应用回整个元组,我不确定这种方法是否适用于顶级字段(顺便说一句,SQL cast语法不允许指定字段的可空性) 我的问题是,有没有更好的方法来实现这一点?类似于nullable()函数,可以应用于表达式以将其标记为可为null,类似于cast的工作方式 示例代码:Apache spark spark sql和dataframes中控制字段的可空性,apache-spark,dataframe,apache-spark-sql,Apache Spark,Dataframe,Apache Spark Sql,我正在使用spark sql的DataFrame实现一个通用的数据集成组件。 基本思想是,用户通过命名字段并使用简单的sql片段(可以出现在select子句中的片段)映射字段来配置字段,组件添加这些列并将它们分组到结构字段中(使用DSL列) 稍后的处理将这些结构字段中的一些字段分组到一个数组中,此时我遇到了一个问题,即其中一个字段在一个元组中可为null,而在另一个元组中不可为null 由于字段分组在一个结构中,所以我能够提取结构类型,修改它并使用Column.cast方法将其应用回整个元组,我
val df = (1 to 8).map(x => (x,x+1)).toDF("x","y")
val df6 = df.select(
functions.struct( $"x" + 1 as "x1", $"y" + 1 as "y1" ) as "struct1",
functions.struct( $"x" + 1 as "x1", functions.lit(null).cast( DataTypes.IntegerType ) as "y1" ) as "struct2"
)
val df7 = df6.select( functions.array($"struct1", $"struct2") as "arr" )
此操作失败,但出现以下异常:
由于数据类型不匹配,无法解析“数组(结构1,结构2)”:
函数数组的输入应该是相同的类型,但是
[struct,struct];
org.apache.spark.sql.AnalysisException:无法解析
数据类型不匹配导致的“数组(结构1,结构2)”:函数的输入
数组应该是相同的类型,但它是[struct,
结构]
修复程序如下所示:
//val df7 = df6.select( functions.array($"struct1", $"struct2") as "arr" )
val df7 = df6.select( functions.array($"struct1" cast df6.schema("struct2").dataType, $"struct2" ) as "arr" )
您可以使用创建
选项[Int]
的udf
使其更干净一些:
val optionInt = udf[Option[Int],Int](i => Option(i))
然后,在为struct1
创建y1
时,需要使用optionInt($“y”+1)
。其他一切都保持不变(尽管为简洁起见进行了编辑)
然后
df6。选择(数组($“struct1”,“$“struct2”)作为“arr”)
工作正常。这可能会工作,但它有一些不足之处首先它需要快速定义udf,然后必须为所用的所有类型定义它,另一件事是Catalyst不知道udf内部发生了什么,这可能意味着一些优化机会的损失。
val df6 = df.select(
struct($"x" + 1 as "x1", optionInt($"y" + 1) as "y1" ) as "struct1",
struct($"x" + 1 as "x1", lit(null).cast(IntegerType) as "y1" ) as "struct2"
)