我的方案解释如下: - (以下实验尝试使用Spark Shell)
我有一个数据框,其中包含客户ID和客户名称列。现在我想通过Spark UDF对其执行追加操作。
以下示例:
case class Customer(customerId: Int, customerName: String)
val x = sc.parallelize(Array(Customer(123, "User1"),Customer(456, "User2")))
val df = sqlContext.createDataFrame(x)
df.registerTempTable("df")
以上步骤将创建数据框并以" df"的名称注册。
现在注册Spark UDF(追加)
sqlContext.udf.register("append", (s: String, p1: String) => { if (s != null) s + p1 else p1 })
然后我将值分配给变量。此值需要附加customerName列值
val appendString = "'\""
这里我的追加字符串包含值中的单引号和双引号("),如果我尝试执行以下spark查询: -
sqlContext.sql(s"SELECT append(`customerName`, $appendString) as `customerName APPEND` from df").show
结果将是一个Parse异常
java.lang.RuntimeException:[1.68]失败:标识符期望SELECT 从df追加(
customerName
,'")为customerName APPEND
^ 在scala.sys.package $ .error(package.scala:27) 在org.apache.spark.sql.catalyst.AbstractSparkSQLParser.parse(AbstractSparkSQLParser.scala:36)
我的预期输出是
customerName APPEND
用户1'"
用户2'"
我的发现如下:
如果值中只有单引号,那么我可以成功执行如下查询: -
val appendString = "'"
sqlContext.sql(s"""SELECT append(`customerName`, \"$appendString\") as `customerName APPEND` from df""").show
如果值中只有双引号,那么我可以成功执行如下查询: -
val appendString = "\""
sqlContext.sql(s"""SELECT append(`customerName`, '$appendString') as `customerName APPEND` from df""").show
但如果在同一个字符串中存在单引号和双引号("),我无法找到使用Spark Data Frame Select表达式API执行此操作的方法
我的火花版本是1.6.0
非常感谢任何帮助。
答案 0 :(得分:0)
您可以使用String Interpolation从String中获取值。但要使您的UDF首先工作,您需要将appendString
值更改为
val appendString = """"'\"""""
它会将"'\""
值保存到appendString变量,您需要将该值传递给UDF。请注意,您需要跳过"
并将'\"
括在双引号周围,以使其成为UDF的有效字符串字符。现在使用以下语句来获得结果
sqlContext.sql(s"""SELECT append(customerName, $appendString) as `customerName APPEND` from df""").show
//output
+-------------------+
|customerName APPEND|
+-------------------+
| User1'"|
| User2'"|
+-------------------+