从UDF中的Spark SQL行提取嵌套数组

时间:2018-07-13 11:46:02

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

我正在使用DataFrames,需要提取数据。 我有很多嵌套级别,所以我先进行了爆炸和选择,但是后来我将UDF用于嵌套级别。

我有一个使用$"Root.Obj"的UDF,它是一个数组,我希望它返回一个Array [MyObj]。
我的输出类:

case class MyObj(fieldA: Boolean, fieldB: String, fieldC: Array[MyNested])
case class MyNested(field1: Long, field2: String)

这是输入模式的简称:

 |-- Obj: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- FieldA: boolean (nullable = true)
 |    |    |-- FieldB: string (nullable = true)
 |    |    |-- FieldC: array (nullable = true)
 |    |    |    |-- element: struct (containsNull = true)
 |    |    |    |    |-- Field1: long (nullable = true)
 |    |    |    |    |-- Field2: string (nullable = true)
 |    |    |-- FieldD: boolean (nullable = true)

我的UDF:

def extractObjs: UserDefinedFunction = udf {
  (objs: Seq[Row]) ⇒
    objs.map {
      obj ⇒
        MyObj(
          obj.getAs[Boolean]("FieldA"),
          obj.getAs[String]("FieldB"),
          extractNested(obj.get???("FieldC"))
        )
    }
}

def extractNested(nesteds: ???): Array[MyNested] = {
  ???
}

这是更复杂的IRL,因为我需要从其他位置检索值,并且有更多的嵌套数组。 而且,Obj和FieldC的输入结构比这里复杂得多,我无法(或不想)为其创建案例类。因为我需要在多个地方进行此操作,所以说我不知道​​FieldC元素的“结构”。

我的问题是提取“ FieldC”数组。我想要一个Seq [Row],但我无法实现这一点,getStruct只给我一行,并且由于scala.collection.mutable.WrappedArray$ofRef cannot be cast to org.apache.spark.sql.Row之后,getSeq [Row]引发错误。

1 个答案:

答案 0 :(得分:0)

结构映射到UDF中的Row,因此Seq[Row]可以访问结构数组,例如:

def extractObjs: UserDefinedFunction = udf {
  (objs: Seq[Row]) ⇒
    objs.map {
      obj ⇒
        MyObj(
          obj.getAs[Boolean]("FieldA"),
          obj.getAs[String]("FieldB"),
          extractNested(obj.getAs[Seq[Row]]("FieldC"))
        )
    }
}

def extractNested(nesteds: Seq[Row]): Array[MyNested] = {
  nesteds.map(r => MyNested(r.getAs[Long]("Field1"),r.getAs[String]("Field2"))).toArray
}