在Spark中为UDF建模可选参数的最佳方法是什么?

时间:2019-12-20 06:41:50

标签: scala apache-spark apache-spark-sql user-defined-functions

似乎无法在UDF中使用可选/默认参数。 jira建议针对这种用例使用两个不同的UDF。

我的代码如下:

dataset.select(RecordProvider.getKeyUDF(sparkArguments.getDatasetArguments)(col(hashKeyName), col(rangeKeyName)).as("key"),
               RecordProvider.getValueUDF(avroSchema)(to_json(struct(dataset.columns.map(col): _*))).as("value"))

UDF看起来像这样,

def getKeyUDF(datasetArguments: DatasetArguments) = udf((hashKey: String, rangeKey: String) => {
.....
})

在这种情况下,rangeKeyName可以为null,这意味着该数据集不存在rangeKey列。我的UDF已注册为rangeKey处理null的函数。

我正在努力在没有{if1)if的情况下完成此工作,而在整个dataset.select周围则有两个UDF。那是唯一的方法吗?另外,由于我使用的是curring,因此无法为UDF使用函数(val),因此必须坚持使用方法(def)。

2 个答案:

答案 0 :(得分:1)

您可以添加不存在的仅具有空值的列。或者,您可以使用if-else检查该列是否存在,并将rangeKey替换为不存在的空列。这样,您就可以在两种情况下使用相同的UDF

添加不存在的空列:

if (!dataset.columns.contains(rangeKeyName))
  dataset = dataset.withColumn("rangeKeyName", lit(None).cast(StringType()))

使用if-else:

if (dataset.columns.contains(rangeKeyName)) {
  // Same as before
} else {
  dataset.select(RecordProvider.getKeyUDF(sparkArguments.getDatasetArguments)(col(hashKeyName), lit(None).cast(StringType())).as("key"),
                 RecordProvider.getValueUDF(avroSchema)(to_json(struct(dataset.columns.map(col): _*))).as("value"))
}

答案 1 :(得分:1)

您也可以在列本身上使用when(condition,result1).otherwise(result2)。 lit()可用于避免NULL。可以是任何数据类型。

    import org.apache.spark.sql.functions._
    dataset.select(getKeyUDF(when(col("hashKeyName").isNull,lit("")).otherwise(col("hashKeyName")),col("rangeKeyName")).as("key"))