为什么$不能使用String类型的值(并且只能直接使用字符串文字)?

时间:2018-01-11 07:32:34

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

我有以下模仿枚举的对象:

object ColumnNames {
     val JobSeekerID = "JobSeekerID"
     val JobID = "JobID"
     val Date = "Date"
     val BehaviorType = "BehaviorType"   
}

然后我想按列对DF进行分组。以下内容无法编译:

userJobBehaviourDF.groupBy($(ColumnNames.JobSeekerID))

如果我将其更改为

userJobBehaviourDF.groupBy($"JobSeekerID")

有效。

如何一起使用$ColumnNames.JobSeekerID来执行此操作?

2 个答案:

答案 0 :(得分:2)

$是一个名为string interpolator的Scala功能。

  

从Scala 2.10.0开始,Scala提供了一种从数据创建字符串的新机制:String Interpolation。 String Interpolation允许用户直接在已处理的字符串文字中嵌入变量引用。

Spark将Spark SQL中的字符串插补器用于convert $"col name" into a column

scala> spark.version
res0: String = 2.3.0-SNAPSHOT

scala> :type $"hello"
org.apache.spark.sql.ColumnName

ColumnName类型是Column类型的子类型,这就是为什么您可以使用$ - 前缀字符串作为列引用,其中Column类型的值是预期的。

import org.apache.spark.sql.Column
val c: Column = $"columnName"
scala> :type c
org.apache.spark.sql.Column
  

如何使用$和ColumnNames.JobSeekerID一起执行此操作?

你不能。

您应该直接使用Column将列名称(在“枚举器”中)映射到$类型(这需要将其类型更改为Column)或使用{{ <} {}需要Columns时才会运行{}}或col

  

col(colName:String):Column 根据给定的列名返回一列。

     

column(colName:String):Column 根据给定的列名返回一个列。

$其他地方

有趣的是Spark MLlib使用$ - ML参数的前缀字符串,但在这种情况下$ column

protected final def $[T](param: Param[T]): T = getOrDefault(param)

还值得一提的是,is just a regular method中使用了$字符串插补器来创建可用于测试或Spark SQL内部探索的逻辑UnresolvedAttributes

import org.apache.spark.sql.catalyst.dsl.expressions._
scala> :type $"hello"
org.apache.spark.sql.catalyst.analysis.UnresolvedAttribute

Scala中的字符串插值器

字符串插值器功能在编译时工作(被解析为正确的值),因此它是一个字符串文字或者它将失败。

$类似于s Catalyst DSL

  

s预先添加到任何字符串文字允许直接在字符串中使用变量。

Scala提供了三种开箱即用的字符串插值方法:sfraw,您可以像Spark一样编写自己的插值器。

答案 1 :(得分:0)

您只能将$与字符串文字(值)一起使用如果您想使用ColumnNames,可以执行以下操作

userJobBehaviourDF.groupBy(userJobBehaviourDF(ColumnNames.JobSeekerID))

userJobBehaviourDF.groupBy(col(ColumnNames.JobSeekerID))

Spark Docs for Column开始,以下是表示列的不同方法:

df("columnName")            // On a specific `df` DataFrame.
col("columnName")           // A generic column no yet associated with a DataFrame.
col("columnName.field")     // Extracting a struct field
col("`a.column.with.dots`") // Escape `.` in column names.
$"columnName"               // Scala short hand for a named column.

希望这有帮助!