上下文
我在数据框输入中有一个事件源数据的示例,如下所示。
SOURCE
其中eventOccurredTime是String类型。这是来源,我想保留它的原始字符串形式(纳秒)
我想使用该字符串来增加一些额外的日期/时间类型数据以供下游使用。下面是一个例子
TARGET
现在我可以在数据帧上执行一些spark sql,如下所示,以获得我想要的结果:
import org.apache.spark.sql.DataFrame
def transformDF(): DataFrame = {
spark.sql(
s"""
SELECT
id,
struct(
event.eventCategory,
event.eventName,
event.eventOccurredTime,
struct (
CAST(date_format(event.eventOccurredTime,"yyyy-MM-dd'T'HH:mm:ss.SSS") AS TIMESTAMP) AS eventOccurredTimestampUTC,
CAST(date_format(event.eventOccurredTime,"yyyy-MM-dd'T'HH:mm:ss.SSS") AS DATE) AS eventOccurredDateUTC,
unix_timestamp(substring(event.eventOccurredTime,1,23),"yyyy-MM-dd'T'HH:mm:ss.SSS") * 1000 AS eventOccurredTimestampMillis,
datesDim.dateSeq AS eventOccurredDateDimSeq
) AS eventOccurredTimeDim,
注意:这是一个片段,对于完整的事件,我必须在这个长SQL中显式执行20次20字符串日期
需要注意的一些事项:
unix_timestamp(substring(event.eventOccurredTime,1,23)
上面我发现我必须对具有纳米精度的日期进行子串,否则将返回null,因此子字符串
xDim.xTimestampUTC
xDim.xDateUTC
xDim.xTimestampMillis
xDim.xDateDimSeq
上面是4个嵌套的xDim结构字段的模式/命名约定,它们存在于预定义的spark模式中,json被用来创建源数据帧。
datesDim.dateSeq AS eventOccurredDateDimSeq
要获得上述' eventOccurredDateDimSeq'字段,我需要加入日期维度表' datesDim' (带有每小时颗粒的静态),其中dateSeq是'键'其中此日期属于每小时桶,其中datesDim.UTC定义为小时
LEFT OUTER JOIN datesDim ON
CAST(date_format(event.eventOccurredTime,"yyyy-MM-dd'T'HH:00:00") AS TIMESTAMP) = datesDim.UTC
该表在spark集群中是全局可用的,因此应该快速查找,但我需要对有效负载中的每个日期丰富进行此操作,它们将具有不同的日期。
dateDimensionDF.write.mode("overwrite").saveAsTable("datesDim")
一般架构模式是,如果字段名称为字符串日期:
x
..有一个&x 39; xDim' struct equiv,紧跟在下面的架构顺序中,如下所述。
xDim.xTimestampUTC
xDim.xDateUTC
xDim.xTimestampMillis
xDim.xDateDimSeq
正如片段中所提到的,虽然在上图中我只是展示了“eventOccuredTime'在上面,通过模式中有更多这些,在较低级别,也需要应用相同的转换模式。
问题:
所以我有一个spark sql(代码片段的完整monty)为1个事件类型执行此操作,并且它是一个大的,显式的SQL语句,它应用了我显示的时间函数和连接),但这是我的问题我需要帮助。
因此,我想尝试创建一个更通用的,功能导向的可重用解决方案,该解决方案遍历嵌套数据框并应用此转换模式,如上所述'
如何定义'它需要的位置'?
也许命名约定是一个好的开始 - 遍历DF,查找具有xDim(' Dim'后缀)模式的任何结构字段,并使用' x'字段作为输入,并按照所描述的命名模式填充xDim。*值?
如何在函数中最好地加入datesDim注册表(它的静态记忆),以便它执行?
解决方案吗
认为需要一个或多个UDF(我们使用Scala),可能单独使用或作为SQL中的片段,但不确定。我认为确保DatesDim查找执行是关键。
或许还有另一种方式?
注意:我正在使用Dataframes / SparkSQL而不是数据集,但每个欢迎选项?
Databricks
注意:实际上我实际上是使用数据库平台,所以对于SQL'高阶函数'中的那些经文。在Dbricks
https://docs.databricks.com/spark/latest/spark-sql/higher-order-functions-lambda-functions.html
....这里有一个灵活的选项,使用' TRANSFORM'作为SQL HOF(可能需要注册一个实用程序UDF并使用它与转换)?
太棒了,感谢火花社区的帮助!对不起,这是设置场景的长篇文章。