我遇到Spark Streaming(Spark 2.2.1)的问题。我正在开发一个实时管道,首先我从Kafka获取数据,然后将结果与另一个表连接,然后将Dataframe发送到ALS模型(Spark ML),它返回一个带有一个额外列预测的流数据帧。问题是当我试图获得得分最高的那一行时,我无法找到解决问题的方法。
我试过了:
Limit
,Take
,sort
dense_rank()
功能我看过Unsupported Operations,但似乎并不多。
我将发送给Kafka队列的最高得分
我的代码如下:
val result = lines.selectExpr("CAST(value AS STRING)")
.select(from_json($"value", mySchema).as("data"))
//.select("data.*")
.selectExpr("cast(data.largo as int) as largo","cast(data.stock as int) as stock","data.verificavalormax","data.codbc","data.ide","data.timestamp_cli","data.tef_cli","data.nombre","data.descripcion","data.porcentaje","data.fechainicio","data.fechafin","data.descripcioncompleta","data.direccion","data.coordenadax","data.coordenaday","data.razon_social","data.segmento_app","data.categoria","data.subcategoria")
result.printSchema()
val model = ALSModel.load("ALSParaTiDos")
val fullPredictions = model.transform(result)
//fullPredictions is a streaming dataframe with a extra column "prediction", here i need the code to get the first row
val query = fullPredictions.writeStream.format("console").outputMode(OutputMode.Append()).option("truncate", "false").start()
query.awaitTermination()
更新
也许我不清楚,所以我附上了我的问题的图像。我还写了一个更简单的代码来补充它:https://gist.github.com/.../9193c8a983c9007e8a1b6ec280d8df25 详细说明我需要的东西。我将不胜感激任何帮助:)
答案 0 :(得分:2)
TL; DR 使用流内部联接(Spark 2.3.0)或使用memory
接收器(或Hive表)进行临时存储。
我认为以下句子很好地描述了你的情况:
问题是当我试图获得得分最高的一行时,我无法找到解决问题的方法。
除了机器学习,因为它为您提供了带有预测的流式数据集,因此专注于在流数据集中的列中查找最大值是真实的情况。
第一步是按如下方式计算最大值(直接从代码中复制):
streaming.groupBy("idCustomer").agg(max("score") as "maxscore")
有了这个,你有两个流媒体数据集可以加入as of Spark 2.3.0(几天前已经发布):
在Spark 2.3中,我们添加了对流 - 流连接的支持,也就是说,您可以加入两个流数据集/数据框。
支持任何类型的列上的内连接以及任何类型的连接条件。
内部加入流媒体数据集,您已完成。
答案 1 :(得分:0)
试试这个:
实现一个提取列最大值的函数,然后使用max
过滤数据帧numberOfRowsInSection
在代码正文中添加:
def getDataFrameMaxRow(df:DataFrame , col:String):DataFrame = {
// get the maximum value
val list_prediction = df.select(col).toJSON.rdd
.collect()
.toList
.map { x => gson.fromJson[JsonObject](x, classOf[JsonObject])}
.map { x => x.get(col).getAsString.toInt}
val max = getMaxFromList(list_prediction)
// filter dataframe by the maximum value
val df_filtered = df.filter(df(col) === max.toString())
return df_filtered
}
def getMaxFromList(xs: List[Int]): Int = xs match {
case List(x: Int) => x
case x :: y :: rest => getMaxFromList( (if (x > y) x else y) :: rest )
}
祝你好运!!