【发布时间】:2020-06-05 09:48:18
【问题描述】:
env:sapk-2.4.5
source.json
{
"group": "1",
"name": "badboi",
"rank": "3",
"fellows": [
{
"name": "David",
"age": "25",
"hobby": "code"
},
{
"name": "John",
"age": "27",
"hobby": "tennis"
},
{
"name": "Anata",
"age": "23",
"hobby": "dance"
}
]
}
我想要的是在每个元素中添加一个新列 'ID'(由 md5 生成,带有 'name' JSON 正文),并在 'fellows' 数组中重命名其他元素的列名,如:
输出.json
{
"group": "1",
"name": "badboi",
"rank": "3",
"fellows": [
{
"ID":"6F94AF80FC86BD2DBFAFA9C90BF33522",
"NAME": "David",
"AGE": "25",
"HOBBY": "code"
},
{
"ID":"CF848467689DD81CAC9E644F8294B641",
"NAME": "John",
"AGE": "27",
"HOBBY": "tennis"
},
{
"ID":"4F11EBFF1667DDD817921279EEBD5451",
"NAME": "Anata",
"AGE": "23",
"HOBBY": "dance"
}
]
}
我的解决方案:
1
我已经尝试使用 'explode' 和 'collect_set' 函数来解决它:
val source = spark.read.option("multiLine", "true").json("/mypath/source.json")
val explode_values = source.select($"group",$"name",$"rank",explode($"fellows").as("explode_fellows"))
val renamedDF = explode_values.select($"group",$"name",$"rank", struct(md5(to_json(struct($"explode_fellows.name".as("NAME")))).as("ID"), $"explode_fellows.name".as("NAME"), $"explode_fellows.age".as("AGE"), $"explode_fellows.HOBBY".as("HOBBY")).as("fellows"))
val result = renamedDF.select($"group", $"name", $"rank", $"fellows").groupBy($"group").agg(first($"name").as("name"),first($"rank").as("rank"), collect_set($"fellows").as("fellows"))
那么结果的架构是:
root
|-- group: string (nullable = true)
|-- name: string (nullable = true)
|-- rank: string (nullable = true)
|-- fellows: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- ID: string (nullable = true)
| | |-- NAME: string (nullable = true)
| | |-- AGE: string (nullable = true)
| | |-- HOBBY: string (nullable = true)
2
使用 'array_zip' 只能重命名列:
val result2 = source.select($"group", $"name", $"rank", arrays_zip($"fellows.name", $"fellows.age", $"fellows.hobby").cast("array<struct<NAME: string, AGE:string, HOBBY:string>>").as("fellows"))
那么结果的架构是:
root
|-- group: string (nullable = true)
|-- name: string (nullable = true)
|-- rank: string (nullable = true)
|-- fellows: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- NAME: string (nullable = true)
| | |-- AGE: string (nullable = true)
| | |-- HOBBY: string (nullable = true)
注意:
“爆炸”和“收集”解决方案不符合我的要求,因为它太复杂了,
或者如果您可以在我的解决方案2 中添加 md5 ID 生成功能会有很大帮助。
如果您能给我一些建议,不胜感激。
【问题讨论】:
标签: apache-spark pyspark apache-spark-sql spark-streaming