在不使用explode的情况下在Dataframe内的Array中获取嵌套的StructType值

时间:2017-09-07 19:37:53

标签: scala apache-spark

我正在尝试编写一个udf或者只是一些sql查询来获取嵌套Struct的值。

架构:

StructType(StructField(Parameters,ArrayType(StructType(StructField(**Name**,StringType,true), StructField(Value,StringType,true)),true),true))

我想访问名称的值,并过滤掉名称不在的数据(“BOB”,“Jone”,“Adam”)。< / p>

出于规模目的,爆炸对我来说太慢了。我需要更好的表现。

由于

1 个答案:

答案 0 :(得分:0)

您甚至可以在列名中使用点(.)在数组中引用嵌套列 - 然后创建一个简单的UDF来检查其中一个值是否与您的&#34;有趣的名称相匹配&#34;名单。类似的东西:

import org.apache.spark.sql.functions._
import spark.implicits._ 

// "df" contains some data with the right schema:
df.printSchema()
// root
//  |-- Parameters: array (nullable = true)
//  |    |-- element: struct (containsNull = true)
//  |    |    |-- Name: string (nullable = true)
//  |    |    |-- Value: string (nullable = true)

df.show()
// +--------------------+
// |          Parameters|
// +--------------------+
// | [[Bob,1], [Jane,2]]|
// |[[Adam,1], [Jane,6]]|
// |[[Joan,3], [John,5]]|
// +--------------------+

// we only want the record where names include these:
val interestingNames = Seq("Bob", "Adam")

// UDF checking if there's an intersection between given sequence of names and "interesting" ones:
val areNamesIncluded = udf {
  names: Seq[String] => names.intersect(interestingNames).nonEmpty
}

// use "where" with the result of applying this UDF to Parameters.Name:
val result = df.where(areNamesIncluded($"Parameters.Name"))

result.show()
// +--------------------+
// |          Parameters|
// +--------------------+
// | [[Bob,1], [Jane,2]]|
// |[[Adam,1], [Jane,6]]|
// +--------------------+

你可以在没有UDF的情况下实现这一点,使用array_contains函数对每个有趣的名称&#34;然后使用||折叠结果:

val result2 = df.where(interestingNames.map(s => array_contains($"Parameters.Name", s)).fold(lit(false))(_ || _))