动态查询复杂类型

时间:2018-01-21 16:36:00

标签: scala apache-spark

我试图查询具有复杂类型的spark sql数据帧,其中该函数本身应该能够创建和表达式以生成嵌套复杂数据类型的列数据帧。 说

case class SubRecord(x: Int)
case class ArrayElement(foo: String, bar: Int, vals: Array[Double])
case class Record(
  an_array: Array[Int], a_map: Map[String, String], 
  a_struct: SubRecord, an_array_of_structs: Array[ArrayElement])

val df = sc.parallelize(Seq(
  Record(Array(1, 2, 3), Map("foo" -> "bar"), SubRecord(1),
         Array(
           ArrayElement("foo", 1, Array(1.0, 2.0)),
           ArrayElement("bar", 2, Array(3.0, 4.0)))),
  Record(Array(4, 5, 6), Map("foz" -> "baz"), SubRecord(2),
         Array(ArrayElement("foz", 3, Array(5.0, 6.0)), 
               ArrayElement("baz", 4, Array(7.0, 8.0))))
)).toDF

引自Querying Spark SQL DataFrame with complex types

用于提取地图类型查询的

可以是

df.select($"a_map.foo").show

现在,如果我有

case class Record(
  an_array: Array[Int], a_map_new: Map[String, Array[ArrayElement]], 
  a_struct: SubRecord, an_array_of_structs: Array[ArrayElement])

而不是Map [String,String],如何创建一个在数组的情况下获取名称或索引的udf,并为复杂数据类型中的嵌套元素生成结果。 假设现在我想查询vals[0] contained in a_map_new

1 个答案:

答案 0 :(得分:1)

在这种情况下,如果您有明确定义的记录类型,我建议使用强类型Dataset

val result = df.as[Record].map(_.a_map_new.mapValues(_.headOption))

result.printSchema
// root
//  |-- value: map (nullable = true)
//  |    |-- key: string
//  |    |-- value: struct (valueContainsNull = true)
//  |    |    |-- foo: string (nullable = true)
//  |    |    |-- bar: integer (nullable = false)
//  |    |    |-- vals: array (nullable = true)
//  |    |    |    |-- element: double (containsNull = false)

udf障碍是它的不对称性:

  • 它获取内部类型Row
  • 应返回外部类型。
  • 必须具有静态定义的返回类型。

任何返回struct的通用解决方案都知道如何map到外部类型。我想你可以设计这样的东西(伪代码)

def f(mapper: Row => T) = udf((map: Map[U, Row]) => map.mapValues(mapper(_)))