在Clojure中编写Spark Structured Streaming示例时出错

时间:2017-10-10 01:07:34

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

我正在尝试在Clojure中重写Spark Structured Streaming示例。

该示例使用Scala编写如下:

conditional expression

(ns flambo-example.streaming-example
  (:import [org.apache.spark.sql Encoders SparkSession Dataset Row]
           [org.apache.spark.sql.functions]
           ))

(def spark
  (->
   (SparkSession/builder)
   (.appName "sample")
   (.master "local[*]")
   .getOrCreate)  
  )


(def lines
  (-> spark
      .readStream
      (.format "socket")
      (.option "host" "localhost")
      (.option "port" 9999)
      .load      
      )
  )

(def words
  (-> lines
      (.as (Encoders/STRING))      
      (.flatMap #(clojure.string/split  % #" " ))      
      ))

以上代码会导致以下异常。

;;由java.lang.IllegalArgumentException引起 ;;找不到匹配的方法:class的flatMap ;; org.apache.spark.sql.Dataset

如何避免错误?

1 个答案:

答案 0 :(得分:1)

您必须遵循签名。 Java Dataset API提供了Dataset.flatMap的两个实现,其中一个实现了scala.Function1

def flatMap[U](func: (T) ⇒ TraversableOnce[U])(implicit arg0: Encoder[U]): Dataset[U] 

和第二个采用Spark自己的o.a.s.api.java.function.FlatMapFunction

def flatMap[U](f: FlatMapFunction[T, U], encoder: Encoder[U]): Dataset[U] 

前者对你来说相当无用,但你应该能够使用后者。可以使用RDD访问的flambo API flambo.api/fn uses macros to create Spark friendly adapters - 我不确定这些是否可以直接与Datasets一起使用,但您应该能够如果需要,请调整它们。

由于您不能依赖隐式Encoders,因此您还必须提供与返回类型匹配的显式编码器。

总的来说,你需要一些东西:

(def words
  (-> lines
    (.as (Encoders/STRING))      
    (.flatMap f e)      
  ))

其中f实现FlatMapFunctioneEncoder。一个示例实现:

(def words
  (-> lines
      (.as (Encoders/STRING))      
      (.flatMap
        (proxy [FlatMapFunction] [] 
          (call [s] (.iterator (clojure.string/split s #" ")))) 
        (Encoders/STRING))))

但我想有可能找到一个更好的。

在实践中,我会避​​免键入Dataset,并专注于DataFrameDataset[Row])。