我试图在带有Spark和Kafka的结构化流上使用窗口。 我在非基于时间的数据上使用窗口,所以出现此错误:
'Non-time-based windows are not supported on streaming DataFrames/Datasets;;\nWindow
这是我的代码:
window = Window.partitionBy("input_id").orderBy("similarity")
outputDf = inputDf\
.crossJoin(ticketDf.withColumnRenamed("IDF", "old_IDF")) \
.withColumn("similarity", cosine_similarity_udf(col("IDF"), col("old_IDF"))) \
.withColumn("rank", rank().over(window)) \
.filter(col("rank") < 10)
所以我正在寻找技巧或参考,以在基于非时间的数据上使用窗口...
答案 0 :(得分:1)
Spark结构化流不支持使用over()
的传统SQL窗口(它唯一支持的窗口是基于时间的窗口)。如果您考虑一下,可能是为了避免混淆。有些人可能会错误地认为Spark结构化流可以基于列对整个数据进行分区(这是不可能的,因为流是无限制的输入数据)。
您可以使用groupBy()
。
groupBy()
也是一个全状态操作,除非在我们要进行groupBy操作的列列表中包括一个timestamp列,否则无法在append
模式下实现。例如:
df_result = df.withWatermark("createdAt", "10 minutes" ) \
.groupBy( F.col('Id'), window(F.col("createdAt"), self.acceptable_time_difference)) \
.agg(F.max(F.col('createdAt')).alias('maxCreatedAt'))
在此示例中,createdAt
是时间戳类型的列。请注意,在这种情况下,我们必须事先在timestamp列上调用withWatermrke
,因为Spark无法无限存储状态。
ps:我知道groupBy不能完全像窗口一样工作,但是只要使用mapGroupsWithState
进行简单的联接或自定义功能,就可以实现所需的功能。
答案 1 :(得分:0)
Windows始终需要基于时间的数据,但Spark Structured Streaming
不需要。
您可以使用触发器“ as_soon_as_posible” 创建Spark Structured Streaming
,并且可以按窗口对数据进行分组,分组是按时进行的。
答案 2 :(得分:0)
实际上,窗口仅基于时间...
对于应用程序,我避免避免使用烧瓶。我已经寻找流媒体系统很长时间了...现在我正在使用Kafka,它在我的应用程序中摇摇欲坠! :)
我想与您分享有关结构化流式传输不支持的操作的信息:https://spark.apache.org/docs/latest/structured-streaming-programming-guide.html#unsupported-operations