如何使用FileFormat格式的更新输出模式?

时间:2018-02-28 09:46:59

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

我试图在更新输出模式下使用spark结构化流写入文件。我找到了this StructuredSessionization example,只要配置了控制台格式,它就能正常工作。但是,如果我将输出模式更改为:

 val query = sessionUpdates
  .writeStream
  .outputMode("update")
  .format("json")
  .option("path", "/work/output/data")
  .option("checkpointLocation", "/work/output/checkpoint")
  .start()

我收到以下错误:

 Exception in thread "main" org.apache.spark.sql.AnalysisException: Data source json does not support Update output mode;
        at org.apache.spark.sql.execution.datasources.DataSource.createSink(DataSource.scala:279)
        at org.apache.spark.sql.streaming.DataStreamWriter.start(DataStreamWriter.scala:286)
        at palyground.StructuredStreamingMergeSpans$.main(StructuredStreamingMergeSpans.scala:84)
        at palyground.StructuredStreamingMergeSpans.main(StructuredStreamingMergeSpans.scala)

我可以使用更新模式并使用FileFormat将结果表写入文件接收器吗? 在源代码中,我找到了一个确保追加模式的模式匹配。

2 个答案:

答案 0 :(得分:3)

您无法使用spark结构化流媒体以更新模式写入文件。你需要为它写ForeachWriter。我在这里为每位作家写了简单的文章。您可以根据自己的要求进行修改。

val writerForText = new ForeachWriter[Row] {
    var fileWriter: FileWriter = _

    override def process(value: Row): Unit = {
      fileWriter.append(value.toSeq.mkString(","))
    }

    override def close(errorOrNull: Throwable): Unit = {
      fileWriter.close()
    }

    override def open(partitionId: Long, version: Long): Boolean = {
      FileUtils.forceMkdir(new File(s"src/test/resources/${partitionId}"))
      fileWriter = new FileWriter(new File(s"src/test/resources/${partitionId}/temp"))
      true

    }
  }

val query = sessionUpdates
  .writeStream
  .outputMode("update")
  .foreach(writerForText)
  .start()

答案 1 :(得分:0)

任何Append接收器都需要

FileFormat输出模式,包括。 json,它触发了结构化流validates before starting your streaming query

if (outputMode != OutputMode.Append) {
  throw new AnalysisException(
    s"Data source $className does not support $outputMode output mode")
}

在Spark 2.4中,您可以使用DataStreamWriter.foreach运算符或全新的DataStreamWriter.foreachBatch运算符,它们只接受一个接受批处理的数据集和批处理ID的函数。

foreachBatch(function: (Dataset[T], Long) => Unit): DataStreamWriter[T]