如何以流的形式从csv文件读取数据

时间:2019-02-10 08:21:32

标签: apache-spark apache-spark-sql spark-structured-streaming

我有下表:

DEST_COUNTRY_NAME   ORIGIN_COUNTRY_NAME count
United States       Romania             15
United States       Croatia             1
United States       Ireland             344
Egypt               United States       15  

表表示为数据集。

scala> dataDS
res187: org.apache.spark.sql.Dataset[FlightData] = [DEST_COUNTRY_NAME: string, ORIGIN_COUNTRY_NAME: string ... 1 more field]

我能够按批处理方式对条目进行排序。

scala> dataDS.sort(col("count")).show(100);

我现在想尝试是否可以使用流媒体执行相同的操作。为此,我想必须将文件作为流读取。

scala> val staticSchema = dataDS.schema;
staticSchema: org.apache.spark.sql.types.StructType = StructType(StructField(DEST_COUNTRY_NAME,StringType,true), StructField(ORIGIN_COUNTRY_NAME,StringType,true), StructField(count,IntegerType,true))

scala> val dataStream = spark.
     | readStream.
     | schema(staticSchema).
     | option("header","true").
     | csv("data/flight-data/csv/2015-summary.csv");
dataStream: org.apache.spark.sql.DataFrame = [DEST_COUNTRY_NAME: string, ORIGIN_COUNTRY_NAME: string ... 1 more field]

scala> dataStream.isStreaming;
res245: Boolean = true

但是我无法进一步进步如何以流形式读取数据。

我已经执行了sort转换`过程

scala> dataStream.sort(col("count"));
res246: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [DEST_COUNTRY_NAME: string, ORIGIN_COUNTRY_NAME: string ... 1 more field]

我想现在我应该使用Dataset的{​​{1}}方法。我运行了以下两个命令,但都返回了错误。

writeStream

还有这个

scala> dataStream.sort(col("count")).writeStream.
     | format("memory").
     | queryName("sorted_data").
     | outputMode("complete").
     | start();
org.apache.spark.sql.AnalysisException: Complete output mode not supported when there are no streaming aggregations on streaming DataFrames/Datasets;;

从错误中看来,我应该聚合(组)数据,但是我认为不需要这样做,因为我可以将任何批处理操作作为流运行。

我如何理解如何对作为流到达的数据进行排序?

1 个答案:

答案 0 :(得分:1)

不幸的是,错误消息告诉您的内容是准确的。

您提出的观点:

  

但是我认为我不需要这样做,因为我可以将任何批处理操作作为流运行。

并非没有优点,但它错过了一个基本点,即结构化流并非与微批处理紧密相关。

一个人很容易想到一些无法扩展的骇客

import org.apache.spark.sql.functions._

dataStream
  .withColumn("time", window(current_timestamp, "5 minute"))  // Some time window
  .withWatermark("time", "0 seconds")  // Immediate watermark
  .groupBy("time")
  .agg(sort_array(collect_list(struct($"count", $"DEST_COUNTRY_NAME", $"ORIGIN_COUNTRY_NAME"))).as("data"))
  .withColumn("data", explode($"data"))
  .select($"data.*")
  .select(df.columns.map(col): _*)
  .writeStream
  .outputMode("append")
   ...
  .start()