apache-spark - 为什么 schema_of_json 失败?
问题描述
为什么第二次转型失败?
df
.withColumn("schemaDetected", schema_of_json(lit("""{"Zipcode":704,"ZipCodeType":"STANDARD","City":"PARC PARQUE","State":"PR"}""")))
.show(false)
//shows: struct<City:string,State:string,ZipCodeType:string,Zipcode:bigint>
df
.withColumn("literal", lit("""{"Zipcode":704,"ZipCodeType":"STANDARD","City":"PARC PARQUE","State":"PR"}"""))
.withColumn("schemaDetected", schema_of_json(col("literal")))
.show(false)
// it fails:
// cannot resolve 'schema_of_json(`literal`)' due to data type mismatch: The input json should be a string literal and not null; however, got `literal`.;;
我需要获取一个列架构,但它只接受包含在方法中的“点亮”,当我添加一个列时它会失败。为什么?
解决方案
第二个转换失败,因为当您将包含 json 字符串的列从数据帧传递给schema_of_json
函数时,Spark 无法确定该列的每一行 json 字符串将评估为相同的模式
要理解为什么对所有行使用相同的模式很重要,您必须承认创建schema_of_json
函数的主要用例是为函数推断模式from_json
。
from_json
将 json 字符串转换为struct
,基本上是几个新列。当然,数据框中的所有行都应该具有相同的列。因此,您必须确保from_json
在数据框上使用时,将相同的模式传递给所有行。
正如您在票证SPARK-24642中看到的那样,在原点,您应该能够传递一个不是literal
to的列。但是,它意味着合并每一行的推断模式。例如,如果您有以下数据框:schema_of_json
+------------------+
| json_string |
+------------------+
| {"a": 1} |
| {"b": 2} |
| {"a": 3, "c": 4} |
+------------------+
并且您想将返回的模式传递schema_of_json
给from_json
函数,您必须推断模式STRUCT<a INT, b INT, c INT>
才能为所有行提供一致的模式。为此,您需要转换schema_of_json
为一个聚合函数,该函数将通过迭代参数列的所有值或进行模式推断来构建模式(例如当您阅读 CSV 时)。这被认为不值得。
因此,您不能将数据框列作为参数传递,而只能传递literal
, 您可以使用lit
在SPARK-24709中实现的函数
schema_of_json
后来在 Spark 3.1 中升级(参见SPARK-31044)以能够采用可折叠列,这意味着可以在查询执行之前静态评估的列。这种可折叠列的一个例子是regexp_replace(lit("""{"test":1}""", "1", "2"))
,它不是直接的 aliteral
而是 a 的转换literal
因此,回到您的案例,当您从lit(...)
. 由于 Spark 看不到列的内容,因此无法确定该列的值是否相同。但 Spark 必须确保这些值生成的模式相同,因此必须确保输入值相同。所以它会抛出一个错误,基本上是说“我不能确定对于所有行,该列中包含的 json 字符串都是相同的”
推荐阅读
- javascript - 如何根据 geoJSON 属性的最大值进行插值。使用 Mapbox 绘制、圆形颜色、数据驱动表达式
- python - 如何对 python 说 (a+b) = (b+a) 和 (a*b) = (b*a)
- delphi - Delphi Mouse.curpos 似乎返回了不正确的坐标
- coq - 表明一个术语不等于一个严格更大的术语
- sql - 使用过程的变量进行选择
- sql - 将列 B 中的行复制到表 A 中列的每个类别
- python - 如何通过python将数据保存到mysql
- c - C中的函数参数内存布局(可变参数,...)
- ruby - 传递参数进行初始化和在初始化中设置它们有什么区别?
- jpa - 无法在 JPA 中插入多对多关系