我使用Scala 2.11使用spark 2.1.0。我需要为每个键以Map [String,Any]格式存储状态。解决我问题的正确候选人似乎是mapWithState()
,PairDStreamFunctions
中定义了mapWithState()
。我正在应用{DARream} DStream[Row]
的类型为mapWithState()
。在应用dstream.map(row=> (row.get(0), row))
之前,我这样做:
Tuple2[Any, Row]
现在我的DStream属于def stateUpdateFunction(): (Any, Option[Row], State[Map[String, Any]]) => Option[Row] = {
(key, newData, stateData) => {
if (stateData.exists()) {
var oldState = stateData.get()
stateData.update(Map("count" -> newData.get.get(1), "sum" -> newData.get.get(2)))
Some(Row.fromSeq(newData.get.toSeq.++(Seq(oldState.get("count").get, oldState.get("sum").get))))
}
else {
stateData.update(Map("count" -> newData.get.get(1), "sum" -> newData.get.get(2)))
Some(Row.fromSeq(newData.get.toSeq.++(Seq[Any](null, null))))
}
}
}
类型。在这个DStream上,我应用mapWithState,这是我的updatefunction的外观:
var transformedRow = originalRow.select(concat(upper($"C0"), lit("dummy")), lower($"C1") ...)
现在,更新功能仅在Map中存储2个值(每个键),并将针对“count”和“sum”存储的旧值附加到输入Row并返回。状态映射由输入行中新传递的值更新。我的要求是能够像在DataFrame上那样在输入行上执行复杂的操作,然后将它们存储在状态Map中。换句话说,我希望能够做到这样的事情:
android:windowSoftInputMode="adjustPan"
在update-function中,我无权访问SparkContext或SparkSession。所以,我无法创建单行DataFrame。如果我能做到这一点,应用DataFrame操作并不困难。我为转换的行定义了所有列表达式。
这是我的操作顺序: readState->在输入行上使用此状态执行复杂的DataFrame操作 - >执行更复杂的DataFrame操作以定义状态的新值。
是否可以获取与DataFrame查询/操作相对应的SparkPlan / logicalPlan并将其应用于单个spark-sql Row?我非常感谢这里的任何线索。如果问题不明确或需要更多细节,请告诉我。
答案 0 :(得分:0)
我发现了一个针对给定问题的效率不高的解决方案。通过我们已知的DataFrame操作,我们可以使用已知的模式创建一个空的DataFrame。这个DataFrame可以通过
给我们SparkPlanDataFrame.queryExecution.sparkPlan
此对象是可序列化的,可以传递给stateUpdateFunction。在stateUpdateFunction中,我们可以迭代传递的SparkPlan中包含的表达式,转换它以用相应的文字替换未解析的属性:
sparkPlan.expressions.map(expr=>{
expr.transform{
case attr: AttributeReference =>
println(s"Resolving ${attr.name} to ${map.getOrElse(attr.name, null)}, type: ${map.getOrElse(attr.name, null).getClass().toString()}")
Literal(map.getOrElse(attr.name, null))
case a => a
}
})
此处的地图指的是Row的列值对。在这些转换的表达式上,我们将eval
称为空的InternalRow。这给了我们与每个表达式相对应的结果。因为这种方法涉及解释性评估并且不使用代码生成,所以在现实世界的用例中使用它是低效的。但我会进一步深入研究如何在这里利用代码生成。