将多个条件作为Spark中where子句中的字符串传递

时间:2018-05-24 09:30:26

标签: scala apache-spark apache-spark-sql apache-spark-dataset apache-spark-2.0

我在Spark中使用DataFrame API编写以下代码。

val cond = "col("firstValue") >= 0.5 & col("secondValue") >= 0.5 & col("thirdValue") >= 0.5"
val Output1 = InputDF.where(cond)

我将所有条件作为外部参数的字符串传递,但由于cond应为Column类型,因此会抛出一个解析错误。

例如:

col("firstValue") >= 0.5 & col("secondValue") >= 0.5 & col("thirdValue") >= 0.5

由于我想动态传递多个条件,如何将String转换为Column

修改

我可以在外部以Column的形式阅读条件列表,因为我没有找到任何使用Scala代码将String转换为Column的内容。

2 个答案:

答案 0 :(得分:3)

我相信您可能想要做以下事情:

InputDF.where("firstValue >= 0.5 and secondValue >= 0.5 and thirdValue >= 0.5")

您遇到的错误是运行时的解析错误,如果错误是由传入的错误类型引起的,则甚至无法编译。

正如您在official documentation(此处为Spark 2.3.0提供)中所见,where方法可以采用一系列Column s(如后一个代码段)或表示SQL谓词的字符串(如我的例子所示)。

Spark谓词将解释SQL谓词。但是我相信值得一提的是,您可能有兴趣编写Column而不是连接字符串,因为前一种方法通过消除整个类别的可能错误(例如解析错误)来最小化错误表面。 / p>

您可以使用以下代码实现相同的目标:

InputDF.where(col("firstValue") >= 0.5 and col("secondValue") >= 0.5 and col("thirdValue") >= 0.5)

或更简洁:

import spark.implicits._ // necessary for the $"" notation
InputDF.where($"firstValue" >= 0.5 and $"secondValue" >= 0.5 and $"thirdValue" >= 0.5)

Column很容易组合,比原始字符串更强大。如果您想要应用一组条件,您可以轻松and将它们放在一个函数中,即使在您运行程序之前也可以对其进行验证:

def allSatisfied(condition: Column, conditions: Column*): Column =
    conditions.foldLeft(condition)(_ and _)

InputDF.where(allSatisfied($"firstValue" >= 0.5, $"secondValue" >= 0.5, $"thirdValue" >= 0.5))

当然,您可以通过字符串实现相同的目标,但这最终会变得不那么健壮:

def allSatisfied(condition: String, conditions: String*): String =
    conditions.foldLeft(condition)(_ + " and " + _)

InputDF.where(allSatisfied("firstValue >= 0.5", "secondValue >= 0.5", "thirdValue >= 0.5"))

答案 1 :(得分:0)

我正试图实现类似的目标,对于Scala来说,以下代码对我有用。

导入org.apache.spark.sql.functions。{col,_}

val cond = (col("firstValue") >= 0.5 & 
            col("secondValue") >= 0.5 & 
            col("thirdValue") >= 0.5)

val Output1 = InputDF.where(cond)