优雅的Json在Spark中展平

时间:2016-01-27 02:51:14

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

我在spark中有以下数据框:

val test = sqlContext.read.json(path = "/path/to/jsonfiles/*")  
test.printSchema
root
 |-- properties: struct (nullable = true)
 |    |-- prop_1: string (nullable = true)
 |    |-- prop_2: string (nullable = true)
 |    |-- prop_3: boolean (nullable = true)
 |    |-- prop_4: long (nullable = true)
...

我想要做的是展平此数据框,以便prop_1 ... prop_n存在于顶层。即。

test.printSchema
root
|-- prop_1: string (nullable = true)
|-- prop_2: string (nullable = true)
|-- prop_3: boolean (nullable = true)
|-- prop_4: long (nullable = true)
...

有几种类似问题的解决方案。我能找到的最好的是here。但是,仅当properties类型为Array时,解决方案才有效。就我而言,属性的类型为StructType

另一种方法是:

test.registerTempTable("test")
val test2 = sqlContext.sql("""SELECT properties.prop_1, ... FROM test""")

但在这种情况下,我必须明确指定每一行,这是不优雅的。

解决此问题的最佳方法是什么?

1 个答案:

答案 0 :(得分:11)

如果你不是在寻找一个递归的解决方案,那么使用star的1.6+点语法应该可以正常工作:

val df = sqlContext.read.json(sc.parallelize(Seq(
  """{"properties": {
       "prop1": "foo", "prop2": "bar", "prop3": true, "prop4": 1}}"""
)))

df.select($"properties.*").printSchema
// root
//  |-- prop1: string (nullable = true)
//  |-- prop2: string (nullable = true)
//  |-- prop3: boolean (nullable = true)
//  |-- prop4: long (nullable = true)

不幸的是,这在1.5及之前不起作用。

如果是这样,您可以直接从架构中提取所需信息。您将在Dropping a nested column from Spark DataFrame中找到一个示例,该示例应该易于调整以适应此场景,另一个示例(Python中的递归架构展平)Pyspark: Map a SchemaRDD into a SchemaRDD