在schema rdd中爆炸json数组

时间:2015-04-27 17:25:23

标签: json scala apache-spark-sql

我有一个json喜欢:

{"name":"Yin", "address":[{"city":"Columbus","state":"Ohio"},{"city":"Columbus","state":"Ohio"}]} 
{"name":"Michael", "address":[{"city":null, "state":"California"},{"city":null, "state":"California"}]}

这里的地址是一个数组,如果我使用sqlContext.jsonfile,我将获得schema rdd中的数据,如下所示:

[Yin , [(Columbus , Ohio) , (Columbus , Ohio)] 
[Micheal , [(null, California) , (null, California)] 

我想爆炸存在的数组,并希望在schema rdd中使用以下格式的数据:

[Yin, Columbus, Ohio] 
[Yin, Columbus, Ohio] 
[Micheal, null, California] 
[Micheal, null, California]

我正在使用spark SQL

1 个答案:

答案 0 :(得分:4)

典型的建议是退出sql,但是如果你想留在SQL中,这是我在邮件列表上询问这个问题的答案(由于某种原因,nabble没有显示响应):< / p>

来自Michael Armbrust

您可以使用横向视图爆炸(使用HiveContext),但似乎缺少的是jsonRDD将json对象转换为结构(具有固定顺序的固定键),并且使用结构中的字段进行访问一个.

val myJson = sqlContext.jsonRDD(sc.parallelize("""{"foo":[{"bar":1},{"baz":2}]}""" :: Nil))
myJson.registerTempTable("JsonTest")​
val result = sql("SELECT f.bar FROM JsonTest LATERAL VIEW explode(foo) a AS f").collect()

myJson: org.apache.spark.sql.DataFrame = [foo: array<struct<bar:bigint,baz:bigint>>]
result: Array[org.apache.spark.sql.Row] = Array([1], [null])

在Spark 1.3中,您还可以通过手动指定JSON的架构,向jsonRDD提示您希望将json对象转换为Maps(非统一键)而不是结构。

import org.apache.spark.sql.types._
val schema =
  StructType(
    StructField("foo", ArrayType(MapType(StringType, IntegerType))) :: Nil)
​
sqlContext.jsonRDD(sc.parallelize("""{"foo":[{"bar":1},{"baz":2}]}""" :: Nil), schema).registerTempTable("jsonTest")
​
val withSql = sql("SELECT a FROM jsonTest LATERAL VIEW explode(foo) a AS a WHERE a['bar'] IS NOT NULL").collect()
​
val withSpark = sql("SELECT a FROM jsonTest LATERAL VIEW explode(foo) a AS a").rdd.filter  {
  case Row(a: Map[String, Int]) if a.contains("bar") => true
  case _: Row => false
}.collect()
schema: org.apache.spark.sql.types.StructType = StructType(StructField(foo,ArrayType(MapType(StringType,IntegerType,true),true),true))
withSql: Array[org.apache.spark.sql.Row] = Array([Map(bar -> 1)])
withSpark: Array[org.apache.spark.sql.Row] = Array([Map(bar -> 1)])