如何在scala中创建一个生成sqlcontext的方法,仅根据类型隐含编码器?

时间:2017-04-13 04:51:00

标签: scala apache-spark apache-spark-sql spark-dataframe

我正在尝试在spark之上构建一个框架,可以自动创建从数据存储到磁盘的数据集。我想做的事情的一个例子是:

var sparkSession: SparkSession = _ // initialized elsewhere

def generateDataset[T <: Product : TypeTag](path: Path): Dataset[T] = {
  val df: DataFrame = generateDataFrameFromPath(path)
  import sparkSession.implicits._
  df.as[T]
}

效果很好。我遇到的问题是尝试将其扩展到Dataframe和其他可以生成隐式编码器的类(如StringInt)。我试图做这样的事情:

var sparkSession: SparkSession = _ // initialized elsewhere

def generateDataset[T : TypeTag](path: Path): Dataset[T] = {
  val df: DataFrame = generateDataFrameFromPath(path)
  typeOf[T] match {
    case t if t =:= typeOf[Row] => df
    case t if t <:< typeOf[Product] =>
      import sparkSession.implicits._
      df.as[T]
  }
}

但是,当我们调用T时,即使我们知道Product.as[T]的子类,编译器也不喜欢这样。

我知道标准方法是使用Encoder上下文绑定/隐式,但是我的调用代码在获取数据之前不知道sparkSession

有没有办法在没有调用者生成编码器的情况下使其工作?

1 个答案:

答案 0 :(得分:0)

尝试生成编码:

def generateDataset[T : TypeTag](path: Path) = {
  val df: DataFrame = generateDataFrameFromPath(path)
    typeOf[T] match {
      case t if t =:= typeOf[Row] => df
      case t if t <:< typeOf[Product] =>
        implicit val enc: org.apache.spark.sql.Encoder[T] =  
          org.apache.spark.sql.catalyst.encoders.ExpressionEncoder()
        df.as[T]
  }
}