[英]How to join two streaming datasets when one dataset involves aggregation
我在下面的代码片段中遇到以下错误 -
线程“main” org.apache.spark.sql.AnalysisException 中的异常:当在没有水印的流数据帧/数据集上存在流聚合时,不支持追加输出模式;;
下面是我的输入模式
val schema = new StructType()
.add("product",StringType)
.add("org",StringType)
.add("quantity", IntegerType)
.add("booked_at",TimestampType)
创建流源数据集
val payload_df = spark
.readStream
.format("kafka")
.option("kafka.bootstrap.servers", "localhost:9092")
.option("subscribe", "test1")
.option("startingOffsets", "latest")
.load()
.selectExpr("CAST(value AS STRING) as payload")
.select(from_json(col("payload"), schema).as("data"))
.select("data.*")
创建另一个完成聚合的流数据帧,然后将其与原始源数据帧连接以过滤掉记录
payload_df.createOrReplaceTempView("orders")
val stage_df = spark.sql("select org, product, max(booked_at) as booked_at from orders group by 1,2")
stage_df.createOrReplaceTempView("stage")
val total_qty = spark.sql(
"select o.* from orders o join stage s on o.org = s.org and o.product = s.product and o.booked_at > s.booked_at ")
最后,我试图用追加输出模式在控制台上显示结果。 我不知道我需要在哪里添加水印或如何解决这个问题。 我的目标是仅过滤掉每个触发器中时间戳高于任何早期触发器中收到的最大时间戳的事件
total_qty
.writeStream
.format("console")
.outputMode("append")
.start()
.awaitTermination()
使用 spark 结构化流,您可以仅使用水印直接在流上进行聚合。 如果您有一列带有事件时间戳的列,您可以这样做:
val payload_df = spark
.readStream
.format("kafka")
.option("kafka.bootstrap.servers", "localhost:9092")
.option("subscribe", "test1")
.option("startingOffsets", "latest")
.load()
.selectExpr("CAST(value AS STRING) as payload")
.select(from_json(col("payload"), schema).as("data"))
.select("data.*")
.withWatermark("event_time", "1 minutes")
在聚合查询中,您有 3 种类型的输出:
附加模式使用水印来删除旧的聚合状态。 但是窗口聚合的输出延迟了withWatermark()
指定的延迟阈值,因为模式语义,行只能在最终确定后(即在越过水印后)添加到结果表一次。 有关更多详细信息,请参阅延迟数据部分。
更新模式使用水印来删除旧的聚合状态。
完整模式不会删除旧的聚合状态,因为根据定义,此模式会保留结果表中的所有数据。
稍后编辑:您必须在 groupBy 方法上添加窗口。 val aggFg = payload_df.groupBy( window($"event_time", "1 minute") , $"org", $"product") .agg(max(booked_at).as("booked_at"))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.