【问题标题】:Pass multiple conditions as a string in where clause in Spark在 Spark 的 where 子句中将多个条件作为字符串传递
【发布时间】:2018-11-03 11:17:00
【问题描述】:

我正在 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

【问题讨论】:

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


    【解决方案1】:

    我相信您可能想要执行以下操作:

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

    您面临的错误是运行时的解析错误,如果错误是由传入的错误类型引起的,它甚至不会编译。

    正如您在 official documentation(此处为 Spark 2.3.0 提供)中看到的那样,where 方法可以采用 Columns 序列(就像在您的后一个 sn-p 中一样)或代表一个字符串SQL 谓词(如我的示例)。

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

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

    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)
    

    Columns 比原始字符串更容易组合并且更健壮。如果您想应用一组条件,您可以轻松地将它们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"))
    

    【讨论】:

    • 这里我将 Condition 作为字符串,因为我在 Spark-submit 命令中将该条件作为参数读取。所以我不能在外部传递列类型。我更新了有问题的最后一行。请看一看。
    • 我添加了一个使用字符串执行相同操作的示例。同样,无需进行任何转换,Spark 已经原生接受 SQL 谓词。
    • 使用它的另一件事你只能执行and操作而不是or
    • 如果外部字符串如下((firstValue >= 0.5 && secondValue >= 0.5) || (thirdValue >= 0.5 && fourthValue >= 0.5)) 那么我们无法使用上面的代码实现它。你能帮我解决这个问题吗?我用谷歌搜索过,但没有找到类似的东西。
    • 很好的答案!构图特别优雅。
    【解决方案2】:

    我试图实现类似的事情,对于 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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-25
      • 1970-01-01
      • 2021-12-07
      • 2013-07-27
      • 1970-01-01
      • 1970-01-01
      • 2015-09-29
      • 2016-08-09
      相关资源
      最近更新 更多