如何正确地将结构函数转换为命名的结构表达式?

0aydgbwb  于 2021-05-27  发布在  Spark
关注(0)|答案(3)|浏览(366)

环境:spark2.4.3

示例.json

{
    "array0": [
        {
            "a": "1",
            "b": "2"
        },
        {
            "a": "3",
            "b": "4"
        }
    ]
}

我需要更改中struct的每个字段名 array0 使用spark sql api创建这样的.json:

{
        "array0": [
            {
                "A": "1",
                "B": "2"
            },
            {
                "A": "3",
                "B": "4"
            }
        ]
    }

负载:

val source = spark.read.format("json").option("multiLine", "true").load("/home/user/Desktop/example.json")

由于一些规范,我不得不用api生成我的结构 struct 这里,还有 named_struct 不是api,所以我不能使用它)

val my_struct = struct(col("x.a").as("A"), col("x.b").as("B"))

因为spark2.4.3转换api中的cos还不受支持,所以我用 expr() 功能

val my_transform = expr("transform("+"array0,"+"x->"+my_struct.expr.sql+")")

它抛出:

org.apache.spark.sql.catalyst.parser.ParseException:
extraneous input 'AS' expecting {')', ','}(line 1, pos 58)

看来 expr() 不支持 my_struct.expr.sql . 我很困惑。
那么我怎样才能给一个正确的structsql字符串呢 expr() ?
或者其他任何人能给我的解决方案?
谢谢您。

imzjd6km

imzjd6km1#

另一种选择-如果你想和 transform ###加载提供的数据

val data =
      """
        |{
        |    "array0": [
        |        {
        |            "a": "1",
        |            "b": "2"
        |        },
        |        {
        |            "a": "3",
        |            "b": "4"
        |        }
        |    ]
        |}
      """.stripMargin
    val df = spark.read
      .option("multiLine", true)
      .json(Seq(data).toDS())
    df.show(false)
    df.printSchema()
    /**
      * +----------------+
      * |array0          |
      * +----------------+
      * |[[1, 2], [3, 4]]|
      * +----------------+
      *
      * root
      * |-- array0: array (nullable = true)
      * |    |-- element: struct (containsNull = true)
      * |    |    |-- a: string (nullable = true)
      * |    |    |-- b: string (nullable = true)
      */
val processedDF = df.withColumn("array0", expr("TRANSFORM(array0, " +
      "x -> named_struct('A', x.a, 'B', x.b))"))
    processedDF.show(false)
    processedDF.printSchema()

    /**
      * +----------------+
      * |array0          |
      * +----------------+
      * |[[1, 2], [3, 4]]|
      * +----------------+
      *
      * root
      * |-- array0: array (nullable = true)
      * |    |-- element: struct (containsNull = false)
      * |    |    |-- A: string (nullable = true)
      * |    |    |-- B: string (nullable = true)
      */
4jb9z9bj

4jb9z9bj2#

你不需要 transform 只需重命名字段,就可以使用schema dsl。重命名结构的最短方法是:

val newDF = df.select(col("array0").cast("array<struct<A:string,B:string>>"))

newDF.printSchema()

它给出:

root
 |-- array0: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- A: string (nullable = true)
 |    |    |-- B: string (nullable = true)

也可以将新模式的 DataType

eagi6jfj

eagi6jfj3#

你试过直接用这个吗

val my_transform = expr("""transform(array0,x->struct(x.a.as("A"), x.b.as("B")))""")

相关问题