{
"type": "some_type",
"payload": {
"data1": {
"id": "1"
},
"data2": {
"id": "1",
},
"data3": {
"id": "1"
},
"dataset1": [{
"data11": {
"id": "1",
},
"data12": {
"id": "1",
}
}],
"masterdata": {
"md1": [{
"id": "1"
},
{
"id": "2"
},
{
"id": "3"
}],
"md2": [{
"id": "1",
},
{
"id": "2",
},
{
"id": "3",
}]
}
}
}
到DataFrame
并保存为临时表以便以后使用它。在此Json中,“payload”节点中的字段始终存在,但“masterdata”中的子节点是可选的。
下一步是为Json的每个子节点创建多个DataFrame,如下所示:
DataFrame data1包含来自所有文件的节点“data1”的数据,看起来像具有列“id”的常规表。
在第一次处理部分后,我的Spark状态如下:
DataFrames:
DATA1(ID),
DATA2(ID),
DATA3(ID),
DATA11(ID),
DATA12(ID),
MD1(ID),
MD2(ID)
出现问题 - 如果目录中的一个JSON文件不包含md2节点,由于NullPointException,我无法在“md2”DataFrame上运行show()
和collect()
。
我会理解,如果所有文件都缺少“md2”节点,那么它无法创建md2 DataFrame,但在这种情况下,我希望md2 DataFrame根本没有来自没有节点md2但包含所有其他节点的json文件的数据。
技术细节:
要从嵌套节点读取数据,我使用的是rdd.map& rdd.flatmap,然后我用自定义列名将其转换为DataFrame
如果我在目录中的所有文件包含所有节点时运行应用程序一切正常,但如果缺少单个文件md2节点应用程序失败.show()或.collect()
BTW如果节点存在但空的一切正常。
有没有办法让Spark支持可选的Json节点或处理rdd.map& flatmap中缺少的节点?
我希望它比以前的问题更清楚
在@Beryllium请求中,这里是我用来获取md2 DataFrame的rdd操作
val jsonData = hiveContext.sql("SELECT `payload`.masterdata.md2 FROM jsonData")
val data = jsonData.rdd.flatMap(row => row.getSeq[Row](0)).map(row => (
row.getString(row.fieldIndex("id"))
)).distinct
val dataDF = data.toDF("id")
答案 0 :(得分:2)
尝试插入filter()
,如下所示:
sqlContext.sql("SELECT payload.masterdata.md2 FROM jsonData")
.rdd
.filter(_.getSeq[Row](0) != null)
.flatMap(row => row.getSeq[Row](0))
.map(row => (row.getString(row.fieldIndex("id"))))
.distinct
.toDF("id")
.show()
这会尽快删除空值:所以它应该更快(至少它更短):
sqlContext
.sql("select t.a.id from (SELECT explode(payload.masterdata.md2) as a FROM jsonData) t")
explode()
爆炸了null
。更简单:首先提取ID,然后提取explode()
:
sqlContext.sql("SELECT explode(payload.masterdata.md2.id) FROM jsonData").show()