我在数据框中有一个表,其中有三列。 city_name,driver_name,车辆列表中的车辆。
我也有一些其他详细信息,例如mysql中每个驱动程序的驱动程序小时数,驱动程序联系方式等。数据库中的表采用以下格式:city_name.driver_name。
scala> val tables = """
[
{"vehicles" : ["subaru","mazda"], "city_name" : "seattle", "driver_name" : "x"},
{"city_name" : "seattle", "driver_name" : "y"},
{"city_name" : "newyork", "driver_name" : "x"},
{"city_name" : "dallas", "driver_name" : "y"}
]
""" | | | | | | |
tables: String =
"
[
{"vehicles" : ["subaru","mazda"], "city_name" : "seattle", "driver_name" : "x"},
{"city_name" : "seattle", "driver_name" : "y"},
{"city_name" : "newyork", "driver_name" : "x"},
{"city_name" : "dallas", "driver_name" : "y"}
]
"
scala> val metadataRDD = sc.parallelize(tables.split('\n').map(_.trim.filter(_ >= ' ')).mkString :: Nil)
metadataRDD: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[5] at parallelize at <console>:30
scala> val metadataDF = spark.read.json(metadataRDD)
metadataDF: org.apache.spark.sql.DataFrame = [city_name: string, driver_name: string ... 1 more field]
scala> metadataDF.show
+---------+-----------+---------------+
|city_name|driver_name| vehicles|
+---------+-----------+---------------+
| seattle| x|[subaru, mazda]|
| seattle| y| null|
| newyork| x| null|
| dallas| y| null|
+---------+-----------+---------------+
对于这些驱动程序中的每一个,我需要应用一个功能并写入镶木地板。我想要做的是使用如下所示的内联函数,但无法正常工作:
metadataDF.map((e) => {
val path = "s3://test/"
val df = sparkJdbcReader.option("dbtable",
e.city_name + "." + e.driver_name).load()
val dir = path + e.driver_name + e.city_name
if (e.vehicles)
do something
else:
df.write.mode("overwrite").format("parquet").save(dir)
})
基本上,问题在于如何使用该内联函数。
答案 0 :(得分:0)
对map()
函数的调用总是使用提供的函数将类型A的给定输入集合转换为类型B的另一个集合。在地图函数调用中,您将数据框保存到存储层[大概是HDFS]。在DataFrameWriter Class上定义的save()
方法的返回类型为 Unit (在Java中将其视为 void )。因此,您的函数将无法正常工作,因为它将DataFrame转换为两种类型:if
块返回的数据类型和else
块返回的Unit。
您可以重构您的代码并将其分为两个块:
import org.apache.spark.sql.functions.{concat,concat_ws,lit,col}
import org.apache.spark.sql.DataFrame
import org.apache.spark.rdd.RDD
val metadataRDD: RDD[String] = sc.parallelize(tables.split('\n').map(_.trim.filter(_ >= ' ')).mkString :: Nil)
val metadataDF: DataFrame = spark.read.json(metadataRDD)
val df_new_col: DataFrame = metadataDF
.withColumn("city_driver",concat_ws(".",col("city_name"),col("driver_name")))
.withColumn("dir",concat(lit("s3://test/"),col("city_name"),col("driver_name")))
您现在有两列,其中有表名及其旁边的路径。您可以收集它们并使用它们读取要以Parquet格式存储的数据框。