我正在努力想出一个优雅的解决方案,将单个数据帧连接到1到N个相关数据帧的单独序列。初步尝试:
val sources = program.attributes.map(attr => {
spark.read
.option("header", value = true)
.schema(program.GetSchema(attr))
.csv(s"${program.programRawHdfsDirectory}/${attr.sourceFile}")
})
val rawDf: DataFrame = sources.reduce((df1, df2) => df1.join(df2, program.dimensionFields, "full"))
// Full of fail:
val fullDf: DataFrame = program.dimensions.filter(d => d.hierarchy != "RAW").reduceLeft((d1, _) => {
val hierarchy = spark.read.parquet(d1.hierarchyLocation).where(d1.hierarchyFilter)
rawDf.join(hierarchy, d1.hierarchyJoin)
})
fullDf.selectExpr(program.outputFields:_*).write.parquet(program.programEtlHdfsDirectory)
reduceLeft的想法不起作用,因为我正在迭代配置对象的集合(维度属性),但我希望从每次迭代返回的是一个数据帧。错误是类型不匹配,这并不奇怪。
问题的核心是我有1到N个“维”对象,它们定义了如何加载现有的层次结构表,以及如何将该表连接到我之前创建的“原始”数据帧。
任何想法如何在没有某种可怕的黑客的情况下创建这些联接?
更新
我想知道这可行吗?我在每个层次结构数据框中都有一个公共字段名称。如果我重命名这个公共字段以匹配我的“原始”数据帧中的相应列,我可以在折叠中执行连接而不显式调用列吗? Spark会默认使用匹配的名称吗?
val rawDf = sources.reduce((df1, df2) => df1.join(df2, program.dimensionFields, "full"))
val hierarchies = program.dimensions.map(dim => {
spark.read.parquet(dim.hierarchyLocation).where(dim.hierarchyFilter).withColumnRenamed("parent_hier_cd", dim.columnName)
})
val fullDf = hierarchies.foldLeft(rawDf) { (df1, df2) => df1.join(df2) }
更新2
不,这不起作用。 Spark尝试交叉连接。
答案 0 :(得分:0)
出于我的目的,我只需要在生成层次结构集时返回一个元组:
val hierarchies = program.dimensions.map(dim => {
val hierarchy = spark.read.parquet(dim.hierarchyLocation).where(dim.hierarchyFilter).alias(dim.hierarchy.toLowerCase)
(dim, hierarchy)
})
然后,当我将它们折叠到rawDf
时,我有构建连接所需的元数据。