结构化流-从相同的流源联接2个数据帧

时间:2019-02-22 08:31:28

标签: python-3.x apache-spark window watermark spark-structured-streaming

我有一个可接收Twitter流的Spark应用。

我添加了一个时间列:

timestamp = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')
timestamp_df = tmp_df2.withColumn('time', unix_timestamp(lit(timestamp), 'yyyy-MM-dd HH:mm:ss').cast("timestamp"))

收集不需要拼合的我需要的字段:

main_df = (
    timestamp_df.selectExpr(['time', 'created_at', 'id',...])
)

我拼合其他部分并将字符串列表转换为字符串:

entities_df = (
    timestamp_df
    .select(['time', 'id', explode('entities.user_mentions').alias('temp')])
    .selectExpr(['time', 'id AS tmp_id', 'temp.screen_name'])
    .withWatermark('time', '10 seconds')
    .groupBy(
        'tmp_id', window('time', '10 seconds', '5 seconds')
    )
    .agg(collect_set('screen_name').alias('tmp_screen_name'))
    .withColumn('entities_user_mentions_screen_name', concat_ws(', ', 'tmp_screen_name'))
)

然后将这两个DataFrame结合在一起以获取所需的数据:

final_df = (
    main_df
    .join(entities_df, main_df.id == entities_df.tmp_id)
    .select(['created_at', 'id', ...])
)

当它运行时,我会得到空的DataFrames。

当我使用以下代码在静态数据上运行代码时:

entities_df = (
    timestamp_df
    .select(['time', 'id', explode('entities.user_mentions').alias('temp')])
    .selectExpr(['time', 'id AS tmp_id', 'temp.screen_name'])
    .groupBy('tmp_id')
    .agg(collect_set('screen_name').alias('tmp_screen_name'))
    .withColumn('entities_user_mentions_screen_name', concat_ws(', ', 'tmp_screen_name'))
)

如果运行以上命令(不带水印),则会出现此错误:

  

>流式数据帧/数据集上有流式聚合而没有水印时,不支持追加输出模式

有人可以告诉我我在做什么错吗?

1 个答案:

答案 0 :(得分:1)

好的,我解决了这个问题。只需对代码进行一些更改:

timestamp_df = tmp_df2.withColumn('time', current_timestamp())

代替:

timestamp = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')
timestamp_df = tmp_df2.withColumn('time', unix_timestamp(lit(timestamp), 'yyyy-MM-dd HH:mm:ss').cast("timestamp"))

为此,我认为这不会有所作为,但我没有尝试。

对于Entitys_df:

entities_df = (
    timestamp_df
    .select(['time', 'id', explode('entities.user_mentions').alias('temp')])
    .selectExpr(['time', 'id AS tmp_id', 'temp.screen_name'])
    .withWatermark('time', '5 seconds')
    .groupBy(
        'tmp_id',
        window('time', '5 seconds')
    )
    .agg(collect_set('screen_name').alias('tmp_screen_names'))
    .withColumn('entities_user_mentions_screen_names', concat_ws(', ', 'tmp_screen_names'))
)