Scala 2.11及;Spark 2.0.0动态创建案例类对数据集进行编码
我正在尝试将我的应用程序从Spark 1.6.2更新到2.0.0,我的问题是从Dataframe(我读过的拼花地板)创建一个数据集 我知道我可以使用case类或tuple来键入Dataframe,然后拥有一个数据集,但在运行之前,我不知道将加载哪些数据给用户,所以列的类型和数量是多少 要加载数据,我使用SparkSession从拼花地板读取数据,如下所示:Scala 2.11及;Spark 2.0.0动态创建案例类对数据集进行编码,scala,apache-spark,Scala,Apache Spark,我正在尝试将我的应用程序从Spark 1.6.2更新到2.0.0,我的问题是从Dataframe(我读过的拼花地板)创建一个数据集 我知道我可以使用case类或tuple来键入Dataframe,然后拥有一个数据集,但在运行之前,我不知道将加载哪些数据给用户,所以列的类型和数量是多少 要加载数据,我使用SparkSession从拼花地板读取数据,如下所示: spark.read.schema(schema).parquet(dataPath) schemaOfData是一个StructType
spark.read.schema(schema).parquet(dataPath)
schemaOfData是一个StructType,由一个列表[Map[String,String]]实例化,该列表包含列的名称及其类型(即else String-else-Double)
我在StackOverflow上发现了这一点,但如果没有更简单的方法来解决我的问题,我很难理解它和guest:
感谢您创建从spark数据类型到Scala本机数据类型的隐式转换 然后将该类型映射到具有Spark DataFrame的StructFields的模式
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.types._
val spark = SparkSession
.builder
.appName("Movies Reviews")
.config("spark.master", "local")
.getOrCreate()
import spark.implicits._
val someDF = Seq(
(8, "bat"),
(64, "mouse"),
(-27, "horse")
).toDF("number", "word")
someDF.printSchema()
def schemaCaseClass(schema:StructType, className:String)
(implicit sparkTypeScala:DataType => String):String = {
def structField(col:StructField):String = {
val sparkTypes = sparkTypeScala(col.dataType)
col match {
case x if x.nullable => s" ${col.name}:Option[$sparkTypes]"
case _ => s" ${col.name}:$sparkTypes"
}
}
val fieldsName = schema.map(structField).mkString(",\n ")
s"""
|case class $className (
| $fieldsName
|)
""".stripMargin
}
implicit val scalaTypes:DataType => String = {
case _: ByteType => "Byte"
case _: ShortType => "Short"
case _: IntegerType => "Int"
case _: LongType => "Long"
case _: FloatType => "Float"
case _: DoubleType => "Double"
case _: DecimalType => "java.math.BigDecimal"
case _: StringType => "String"
case _: BinaryType => "Array[Byte]"
case _: BooleanType => "Boolean"
case _: TimestampType => "java.sql.Timestamp"
case _: DateType => "java.sql.Date"
case _: ArrayType => "scala.collection.Seq"
case _: MapType => "scala.collection.Map"
case _: StructType => "org.apache.spark.sql.Row"
case _ => "String"
}
println(schemaCaseClass(someDF.schema, "someDF"))
据我所知,性能应该优于使用map,而不改变我应用程序中的所有遗留代码,请检查:在Scala中编码类型通用逻辑需要在运行时获得某种类型的代码,这可能非常麻烦。Spark使用表达式对此进行旁路,为列类型启用类似SQL的行为(因此在运行时进行检查)。这就是为什么您可能希望利用DataFrames的类型泛型性或Row的灵活性来处理它,而不是自己做任何事情。或者?请解释一下你的答案