从case类生成Spark StructType / Schema

oprakyz7  于 6个月前  发布在  Apache
关注(0)|答案(4)|浏览(90)

如果我想从case class中创建一个StructType(即DataFrame.schema),有没有办法不创建DataFrame?我可以很容易地做到:

case class TestCase(id: Long)
val schema = Seq[TestCase]().toDF.schema

字符串
但是,当我只需要模式时,实际创建DataFrame似乎有些多余。
(If你很好奇,这个问题背后的原因是我定义了一个UserDefinedAggregateFunction,为了这样做,你覆盖了两个返回StructTypes的方法,我使用了case类。

fkvaft9z

fkvaft9z1#

你可以用SQLContext.createDataFrame的方法来做:

import org.apache.spark.sql.catalyst.ScalaReflection
val schema = ScalaReflection.schemaFor[TestCase].dataType.asInstanceOf[StructType]

字符串

gtlvzcf8

gtlvzcf82#

我知道这个问题已经快一年了,但我遇到了它,并认为其他人也可能想知道我刚刚学会使用这种方法:

import org.apache.spark.sql.Encoders
val mySchema = Encoders.product[MyCaseClass].schema

字符串

dgjrabp2

dgjrabp23#

如果有人想为自定义Java Bean这样做:

ExpressionEncoder.javaBean(Event.class).schema().json()

字符串

sycxhyv7

sycxhyv74#

与其手动复制用于创建传递给toDF的隐式Encoder对象的逻辑,我们可以直接使用它(或者更准确地说,以与toDF相同的方式隐式地使用它):

// spark: SparkSession

import spark.implicits._

implicitly[Encoder[MyCaseClass]].schema

字符串
不幸的是,这实际上遇到了与其他答案中使用org.apache.spark.sql.catalystEncoders相同的问题:Encoder特性是实验性的。

这是如何工作的?Seq上的toDF方法来自DatasetHolder,它是通过spark.implicits._导入的隐式localSeqToDatasetHolder创建的。该函数的定义如下:

implicit def localSeqToDatasetHolder[T](s: Seq[T])(implicit arg0: Encoder[T]): DatasetHolder[T]


如您所见,它接受一个implicitEncoder[T]参数,对于case class,可以通过newProductEncoder计算该参数(也通过spark.implicits._导入)。我们可以通过方便的scala.Predef.implicitly来重现这个隐式逻辑,为我们的case类获取一个Encoder。(默认情况下在作用域中,因为它来自Predef),它将只返回其请求的隐式参数:

def implicitly[T](implicit e: T): T

相关问题