Scala 从Spark数据帧的行创建对象的规范方法是什么?

Scala 从Spark数据帧的行创建对象的规范方法是什么?,scala,apache-spark,apache-spark-sql,influxdb,apache-zeppelin,Scala,Apache Spark,Apache Spark Sql,Influxdb,Apache Zeppelin,我使用的是ApacheZeppelin(0.9.0)和Scala(2.11.12)。我想从数据帧中提取一些数据并将其存储到XDB,稍后在Grafana中可视化,但我无法理解它。我正在尝试一种使用foreach循环的天真方法。其思想是迭代所有行,提取我需要的列,创建一个Point对象(从),然后将其发送到XDB或将其添加到列表,然后在循环后批量发送所有点 数据帧如下所示: +---------+---------+-------------+-----+ |timestamp|sessionId|

我使用的是ApacheZeppelin(0.9.0)和Scala(2.11.12)。我想从数据帧中提取一些数据并将其存储到XDB,稍后在Grafana中可视化,但我无法理解它。我正在尝试一种使用
foreach
循环的天真方法。其思想是迭代所有行,提取我需要的列,创建一个Point对象(从),然后将其发送到XDB或将其添加到列表,然后在循环后批量发送所有点

数据帧如下所示:

+---------+---------+-------------+-----+
|timestamp|sessionId|eventDuration|speed|
+---------+---------+-------------+-----+
|        1|     ses1|          0.0|   50|
|        2|     ses1|          1.0|   50|
|        3|     ses1|          2.0|   50|
我已尝试执行上述操作:

导入scala.collection.mutable.ListBuffer
导入spark.implicits_
导入org.apache.spark.sql_
导入com.paulgoldbaum.influxdbclient_
导入scala.concurrent.ExecutionContext.Implicits.global
val influxdb=influxdb.connect(“172.17.0.4”,8086)
val database=influxdb.selectDatabase(“测试”)
var influxData=新的ListBuffer[点]()
dfAnalyseReport.foreach(行=>
{
val点=点(“加速度”)
.addTag(“speedBin”,row.getLong(3.toString)
.addField(“eventDuration”,行.getDouble(2))
扩展数据+=点
}
)
val influxData=influxData.toList
database.bulkWrite(influxDataList)
我在这里看到的唯一一件事是一个神秘的
java.lang.ClassCastException
,没有其他信息,既没有在笔记本输出中,也没有在齐柏林飞艇Docker容器的日志中。错误似乎出现在foreach中的某个地方,甚至在我注释掉最后两行时也是如此

我还尝试从中调整方法1,对列使用case类,但没有效果。我让它运行时没有错误,但结果列表是空的。不幸的是,我删除了那个尝试。如果有必要的话,我可以重建它,但我在这方面花了太多时间,我相当确定我对如何实现这一点有一些基本的误解

还有一个问题:我还尝试在DB构建时(而不是批量)将每个点写入DB。唯一的区别是,我没有附加到
ListBuffer
中,而是执行了
database.write(point)
操作。当在循环外部使用伪点执行时,它会毫无问题地通过-数据以InfluxDB结束-但在循环内部它会导致
org.apache.spark.SparkException:Task not serializable


有人能给我指出正确的方向吗?我应该如何解决这个问题?

我会使用RDD映射方法,并将结果收集到一个列表中:

val influxDataList = dfAnalyseReport.rdd.map(
    row => Point("acceleration")
           .addTag("speedBin", row.getInt(3).toString)
           .addField("eventDuration", row.getDouble(2))
).collect.toList

数据帧的模式是什么?速度列的类型是int还是long?如果在int列上使用getLong,可以得到一个classcastexception。没错,它是一个整数。将其更改为getInt修复了ClassCastException,并且没有出现错误。但是,结果列表和listbuffer仍然为空。有什么好处?我是否缺少
influxData
范围内的内容?请参阅下面的答案。我认为使用
rdd.map
比使用
df.foreach
要好。这就做到了,谢谢!你能告诉我(或者建议进一步阅读)为什么我最初的方法不起作用吗?我不太确定,可能列表缓冲区没有很好地并行化。