Apache spark 如何在pyspark中的流式查询中生成会话窗口?

Apache spark 如何在pyspark中的流式查询中生成会话窗口?,apache-spark,pyspark,databricks,spark-structured-streaming,azure-databricks,Apache Spark,Pyspark,Databricks,Spark Structured Streaming,Azure Databricks,下面的代码与批处理的预期一样工作,但在流式查询中失败,出现了臭名昭著的AnalysisException: 流式数据帧/数据集不支持非基于时间的窗口 我只是对这一部分感到好奇,“所以推荐的替代方法是使用mapGroupsWithState()方法”。你在哪里找到这个建议的?我并不是说这是不正确的,我只是想在更广泛的背景下读/听。谢谢。@JacekLaskowski:基本上我遇到的所有其他建议方法都以这样或那样的方式处理mapGroupsWithState()。另外,Structure Sessi

下面的代码与批处理的预期一样工作,但在流式查询中失败,出现了臭名昭著的
AnalysisException

流式数据帧/数据集不支持非基于时间的窗口


我只是对这一部分感到好奇,“所以推荐的替代方法是使用mapGroupsWithState()方法”。你在哪里找到这个建议的?我并不是说这是不正确的,我只是想在更广泛的背景下读/听。谢谢。@JacekLaskowski:基本上我遇到的所有其他建议方法都以这样或那样的方式处理mapGroupsWithState()。另外,Structure Sessionation的官方Spark Github示例也使用了它:您是否有兴趣使用
lag
window函数,或者解决一个更一般的sessionation问题?sessionation。但我还想在后面的步骤中对会话化数据集执行其他操作。看起来您必须使用。
from pyspark.sql.functions import *
from pyspark.sql.window import Window

temp = [
  ('Alice', 1),
  ('Alice', 60),
  ('Alice', 160),
  ('Alice', 1111),
  ('Alice', 1111),
  ('Alice', 1111),
  ('Alice', 1111),
  ('Alice', 1111),
  ('Alice', 1111),
  ('Alice', 1112),
  ('Bob', 3),
  ('Alice', 2),
  ('Bob', 2),
  ('Alice', 3),
  ('Bob', 1)
]

temp_df = spark.createDataFrame(temp, ["user", "ev_timestamp"])

maxSessionDuration = 60 * 10 # Max session duration of 10 minutes.
client_fp_time_window = Window.partitionBy("user").orderBy("ev_timestamp")

rowsWithSessionIds = temp_df \
    .select("user", "ev_timestamp", lag("ev_timestamp", 1).over(client_fp_time_window).alias("prevEvTimestamp")) \
    .select("user", "ev_timestamp", 
            when(
              (col("ev_timestamp").cast('long') - col("prevEvTimestamp").cast('long')) < maxSessionDuration, 0) \
            .otherwise(1).alias("isNewSession")
    ) \
    .select("user", "ev_timestamp", sum("isNewSession").over(client_fp_time_window).alias("sessionId"))

display(rowsWithSessionIds)


sessionsDF = rowsWithSessionIds \
  .groupBy("user", "sessionId") \
  .agg(min("ev_timestamp").alias("startTime"), max("ev_timestamp").alias("endTime"), count("*").alias("count")) \
  .alias('Session')

display(sessionsDF)

user    sessionId   startTime   endTime count
Bob     1           1           3       3
Alice   1           1           160     5
Alice   2           1111        1112    7