我正在火花流中使用CDC Merge脚本。我希望通过一个参数传递selectExpr中的列值,因为每个表的列名都会改变。当我通过字符串变量传递column和struct字段时,由于==>输入''不匹配,我得到了错误,期望
下面是我要参数化的代码段。
var filteredMicroBatchDF=microBatchOutputDF
.selectExpr("col1","col2","struct(offset,KAFKA_TS) as otherCols" )
.groupBy("col1","col2").agg(max("otherCols").as("latest"))
.selectExpr("col1","col2","latest.*")
参考我尝试模仿的脚本:- https://docs.databricks.com/_static/notebooks/merge-in-cdc.html
我已经尝试过以下方法,将列名传递给变量,然后从这些变量中读取selectExpr:-
val keyCols = "col1","col2"
val structCols = "struct(offset,KAFKA_TS) as otherCols"
var filteredMicroBatchDF=microBatchOutputDF
.selectExpr(keyCols,structCols )
.groupBy(keyCols).agg(max("otherCols").as("latest"))
.selectExpr(keyCols,"latest.*")
当我运行脚本时,它给我以下错误:
org.apache.spark.sql.streaming.StreamingQueryException:
mismatched input ',' expecting <<EOF>>
编辑
以下是我在路易斯·米格尔(Luis Miguel)评论后尝试过的方法,效果很好:-
import org.apache.spark.sql.{DataFrame, functions => sqlfun}
def foo(microBatchOutputDF: DataFrame)
(keyCols: Seq[String], structCols: Seq[String]): DataFrame =
microBatchOutputDF
.selectExpr((keyCols ++ structCols) : _*)
.groupBy(keyCols.head, keyCols.tail : _*).agg(sqlfun.max("otherCols").as("latest"))
.selectExpr((keyCols :+ "latest.*") : _*)
var keyColumns = Seq("COL1","COL2")
var structColumns = "offset,Kafka_TS"
foo(microBatchOutputDF)(keyCols = Seq(keyColumns:_*), structColumns = Seq("struct("+structColumns+") as otherCols"))
注意:以下内容会导致错误
foo(microBatchOutputDF)(keyCols = Seq(keyColumns), structColumns = Seq("struct("+structColumns+") as otherCols"))
与上面的工作代码有关的是,这里的keyColumns是硬编码的。因此,我尝试(首先)从参数文件读取,(第二)从窗口小部件读取,这导致了错误,在这里我正在寻找建议和建议:-
第一种方法
def loadProperties(url: String):Properties = {
val properties: Properties = new Properties()
if (url != null) {
val source = Source.fromURL(url)
properties.load(source.bufferedReader())
}
return properties
}
var tableProp: Properties = new Properties()
tableProp = loadProperties("dbfs:/Configs/Databricks/Properties/table/Table.properties")
var keyColumns = Seq(tableProp.getProperty("keyCols"))
var structColumns = tableProp.getProperty("structCols")
keyCols和StructCols在参数文件中定义为:-
keyCols = Col1, Col2
(我也尝试将它们分配为“ Col1”,“ Col2”)
StructCols = offset,Kafka_TS
最后,
foo(microBatchOutputDF)(keyCols = Seq(keyColumns:_*), structColumns = Seq("struct("+structColumns+") as otherCols"))
代码抛出指向第一个逗号的错误(就像它以columns字段作为单个参数一样):
mismatched input ',' expecting <EOF>
== SQL ==
"COL1","COL2""
-----^^^
如果仅在keyCols属性中传递一列,则代码工作正常。
例如。 keyCols = Col1
第二种方法
在这里,我尝试再次从小部件读取键列及其相同的错误。
dbutils.widgets.text("prmKeyCols", "","")
val prmKeyCols = dbutils.widgets.get("prmKeyCols")
var keyColumns = Seq(prmKeyCols)
该小部件将按以下方式传递
"Col1","Col2"
最后,
foo(microBatchOutputDF)(keyCols = Seq(keyColumns:_*), structColumns = Seq("struct("+structColumns+") as otherCols"))
这也给出了相同的错误。
答案 0 :(得分:2)
类似的事情应该起作用:
import org.apache.spark.sql.{DataFrame, functions => sqlfun}
def foo(microBatchOutputDF: DataFrame)
(keyCols: Seq[String], structCols: Seq[String]): DataFrame =
microBatchOutputDF
.selectExpr((keyCols ++ structCols) : _*)
.groupBy(keyCols.head, keyCols.tail : _*).agg(sqlfun.max("otherCols").as("latest"))
.selectExpr((keyCols :+ "latest.*") : _*)
您可以像这样使用:
foo(microBatchOutputDF)(keyCols = Seq("col1", "col2"), structCols = Seq("struct(offset,KAFKA_TS) as otherCols"))