如何在Spark Structured Streaming中获得行前1名?

时间:2018-02-23 14:32:27

标签: scala apache-spark apache-kafka spark-streaming

我遇到Spark Streaming(Spark 2.2.1)的问题。我正在开发一个实时管道,首先我从Kafka获取数据,然后将结果与另一个表连接,然后将Dataframe发送到ALS模型(Spark ML),它返回一个带有一个额外列预测的流数据帧。问题是当我试图获得得分最高的那一行时,我无法找到解决问题的方法。

我试过了:

  1. 应用LimitTakesort
  2. 等SQL函数
  3. dense_rank()功能
  4. 在StackOverflow中搜索
  5. 我看过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 详细说明我需要的东西。我将不胜感激任何帮助:)

    enter image description here

2 个答案:

答案 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 )
}

祝你好运!!