我在Databricks笔记本上使用Spark 2.1和Scala 2.11
什么是TimestampType?
我们从SparkSQL's documentation知道官方时间戳类型是TimestampType,它显然是java.sql.Timestamp的别名:
TimestampType可以在SparkSQL的Scala API
中找到使用架构和数据集API
时,我们有所不同解析{"time":1469501297,"action":"Open"}
from the Databricks' Scala Structured Streaming example
使用Json架构 - >好的(我更喜欢使用优雅的数据集API):
val jsonSchema = new StructType().add("time", TimestampType).add("action", StringType)
val staticInputDF =
spark
.read
.schema(jsonSchema)
.json(inputPath)
使用数据集API - > KO :找不到TimestampType的编码器
创建Event类
import org.apache.spark.sql.types._
case class Event(action: String, time: TimestampType)
--> defined class Event
在databricks上从DBFS读取事件时出错。
注意:使用java.sql.Timestamp
作为“时间”的类型时,我们不会收到错误
val path = "/databricks-datasets/structured-streaming/events/"
val events = spark.read.json(path).as[Event]
错误消息
java.lang.UnsupportedOperationException: No Encoder found for org.apache.spark.sql.types.TimestampType
- field (class: "org.apache.spark.sql.types.TimestampType", name: "time")
- root class:
答案 0 :(得分:7)
组合架构读取方法.schema(jsonSchema)
和包含类型as[Type]
的{{1}}方法将解决此问题。在阅读结构化流媒体文档Creating streaming DataFrames and streaming Datasets
这些示例生成无类型的流式数据框架,这意味着 仅在编译时不检查DataFrame的架构 在提交查询时在运行时检查。有些操作如 map,flatMap等需要在编译时知道类型。去做 那些,你可以将这些无类型的流式数据帧转换为键入的 使用与静态DataFrame相同的方法传输数据集。
java.sql.Timestamp
将输出:
val path = "/databricks-datasets/structured-streaming/events/"
val jsonSchema = new StructType().add("time", TimestampType).add("action", StringType)
case class Event(action: String, time: java.sql.Timestamp)
val staticInputDS =
spark
.read
.schema(jsonSchema)
.json(path)
.as[Event]
staticInputDF.printSchema
答案 1 :(得分:3)
TimestampType
不是java.sql.Timestamp
的别名,而是Spark内部使用的时间戳类型的表示。通常,您不希望在代码中使用TimestampType
。我们的想法是本地支持Spark java.sql.Timestamp
,因此您可以按如下方式定义事件类:
case class Event(action: String, time: java.sql.Timestamp)
在内部,Spark会在编译和优化查询时使用TimestampType
在运行时对值的类型进行建模,但这不是大多数时候您感兴趣的内容。