You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Spark DataFrame中EmbeddedList类型列转为Array<String>

解决OrientDB EmbeddedList UDT转Spark Array及数组拼接问题

一、转换EmbeddedList为Spark原生Array

EmbeddedList是OrientDB自定义的UDT,内部封装了数组结构,可通过两种方式转换为Spark原生Array<String>:

方法1:直接提取UDT内部字段

若EmbeddedList类包含values属性(对应UDT定义的存储字段),可直接在DataFrame中引用该字段提取数组:

import org.apache.spark.sql.functions._

// 提取EmbeddedList内部数组并转为Array<String>
val dfWithArray = df.withColumn("title_array", col("title.values").cast("array<string>"))

方法2:自定义UDF转换

如果直接提取字段无效,可编写自定义UDF解析EmbeddedList:

import org.apache.spark.sql.functions.udf
import com.orientechnologies.spark.udts.EmbeddedList

// 定义UDF:将EmbeddedList转为Array<String>
val embeddedListToArray = udf((el: EmbeddedList) => el.values.asInstanceOf[Array[String]])

// 应用UDF生成新列
val dfWithArray = df.withColumn("title_array", embeddedListToArray(col("title")))

二、修正数组拼接逻辑(解决concat报错)

你遇到的concat报错是因为Spark的concat函数仅支持字符串/二进制类型拼接,不支持数组合并。要合并character(单个字符串)和title_array(字符串数组),可使用flatten函数将嵌套数组扁平化:

val vertices = dfWithArray
  .select(explode(flatten(array(array(col("character")), col("title_array")))) as "x")
  .distinct()
  .rdd.map(_.getAs[String]("x"))
  .zipWithIndex()
  .map(_.swap)

替代方案:用Union实现

如果不需要合并数组,也可分别提取字符和标题元素后再合并:

val chars = df.select(col("character").as("x"))
val titles = df.select(explode(col("title_array")).as("x"))

val vertices = chars.union(titles)
  .distinct()
  .rdd.map(_.getAs[String]("x"))
  .zipWithIndex()
  .map(_.swap)

完整示例代码

import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions._
import com.orientechnologies.spark.udts.EmbeddedList

object OrientDBConversion {
  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder().appName("OrientDBTest").master("local[*]").getOrCreate()
    import spark.implicits._

    // 模拟输入数据
    val df = Seq(
      "Tony Stark" -> EmbeddedList(Array("Iron Man")),
      "James Buchanan Barnes" -> EmbeddedList(Array("Captain America: The First Avenger", "Captain America: The Winter Soldier", "Captain America: Civil War", "Avengers: Infinity War")),
      "Marcus Bledsoe" -> EmbeddedList(Array("Captain America: The Winter Soldier"))
    ).toDF("character", "title")

    // 转换EmbeddedList为Array<String>
    val embeddedListToArray = udf((el: EmbeddedList) => el.values.asInstanceOf[Array[String]])
    val dfWithArray = df.withColumn("title_array", embeddedListToArray(col("title")))

    // 生成目标RDD
    val vertices = dfWithArray
      .select(explode(flatten(array(array(col("character")), col("title_array")))) as "x")
      .distinct()
      .rdd.map(_.getAs[String]("x"))
      .zipWithIndex()
      .map(_.swap)

    // 输出结果
    vertices.foreach(println)
    spark.stop()
  }
}

内容的提问来源于stack exchange,提问作者tbc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 00:45:13