Scala 如何将数据帧与特定路径上的JSON编码行连接起来?
我希望加入2个数据帧(都包含大量JSON),但都是在一个特定的路径下。我希望我可以在相同的操作中完成这项工作,而不必在连接后将其转换为RDD,我认为这可以通过Spark SQL优雅地完成 这两个对象的内容都是动态的,所以我事先不知道整个结构,但每个对象的顶层路径是恒定的 对象1文档Scala 如何将数据帧与特定路径上的JSON编码行连接起来?,scala,apache-spark,apache-spark-sql,Scala,Apache Spark,Apache Spark Sql,我希望加入2个数据帧(都包含大量JSON),但都是在一个特定的路径下。我希望我可以在相同的操作中完成这项工作,而不必在连接后将其转换为RDD,我认为这可以通过Spark SQL优雅地完成 这两个对象的内容都是动态的,所以我事先不知道整个结构,但每个对象的顶层路径是恒定的 对象1文档 { "object1": { "element1" "element1value" ... } } 对象2文件 { "object2": { "ele
{
"object1": {
"element1" "element1value"
...
}
}
对象2文件
{
"object2": {
"element1" "element1value"
...
}
}
预期结果
{
"object1Parent": {
"element1" "element1value"
...
},
"object2Parent": {
"object2": {
"element1" "element1value"
...
}
}
}
联合行动
SQL: "SELECT * FROM object1 r JOIN object2 s ON r.element1 = s.element2"
两个对象的内容都是动态的,所以我事先不知道整个结构
这似乎是一个反对Spark SQL(RDDAPI更是如此)的论点,因为正是这个优化器使Spark SQL如此强大,而且它必须有关于模式的信息才能将优化应用于结构化查询
然而,根据要求,这不一定是正确的
但每种方法的顶层路径都是恒定的
如果object1
后面总是跟着element1
,object2
,并且在join
中使用它们,那就足够了
您只需“解构”不透明的JSON格式,并使其像行一样。使用标准功能,例如
来自_json(e:Column,schema:Column):Column
from_json(e:Column,schema:DataType):Column
将包含JSON字符串的列解析为具有指定架构的StringType为keys type、StructType或StructType的ArrayType的MapType。如果是不可解析的字符串,则返回null
这个schema
参数可以处理模式的动态部分,该参数在运行时可能会更改。它可以作为Spark应用程序的一部分创建(当输入参数为schema:DataType
时),也可以作为数据框的一部分与输入数据一起创建(当schema:Column
时)
您还可以使用get\u json\u object
或json\u tuple
标准函数
从Spark 2.4.0开始,您还可以使用json的模式来推断早期函数的DDL格式列的模式
有很多选择,不是吗
(伪)代码
让我们假设以下两个数据集具有JSON编码的行
val object1 = Seq("""
{
"object1": {
"element1": "element1value",
"object1_only": 1
}
}
""").toDF("json")
val object2 = Seq("""
{
"object2": {
"element1": "element1value",
"object2_only": 2
}
}
""").toDF("json")
您可以使用get\u json\u object
标准函数提取要加入的字段
val obj1_el1 = object1
.select(get_json_object($"json", "$.object1.element1"))
scala> obj1_el1.show
+-----------------------------------------+
|get_json_object(json, $.object1.element1)|
+-----------------------------------------+
| element1value|
+-----------------------------------------+
连接的数据集将如下所示:
val o1 = object1
.withColumn("join_column", get_json_object($"json", "$.object1.element1"))
val o2 = object2
.withColumn("join_column", get_json_object($"json", "$.object2.element1"))
val s = o1.join(o2, Seq("join_column"))
请看这里并获得启发:谢谢,但从我所看到的情况来看,该示例在不转换结构的情况下读取和写入JSON。使用结构可以很容易地更改元素的名称,但我看不出如何在不重新处理数据帧的情况下更改JSON路径结构本身。您可以选择JSON并以JSON形式写入,可能是我太快了。