【问题标题】:Structured steaming groupBy agg collect_list Collect cannot be used in partial aggregations结构化蒸汽 groupBy agg collect_list Collect 不能用于部分聚合
【发布时间】:2018-05-22 02:40:21
【问题描述】:
stateDF
.withWatermark("t","1 seconds")
.groupBy(window($"t","1 minutes","1 minutes"),$"hid")
.agg(collect_list("id"))
.writeStream.outputMode("append")
.format("console").trigger(ProcessingTime("1 minutes"))
.start().awaitTermination()

当我添加“collect_list”时,我会遇到这个问题。 但是通过spark core可以做到。 错误:

java.lang.RuntimeException:Collect 不能用于部分聚合。 在 scala.sys.package$.error(package.scala:27​​) 在...

java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) 在 java.lang.Thread.run(Thread.java:748) 在此处输入代码

【问题讨论】:

    标签: list streaming collect


    【解决方案1】:

    通过我的探索,我对这个问题有两种解决方案。

    方法一:用SPARK-1893修改源代码,但我不建议这样做。

    方法2:自己制作自定义聚合函数(UDAF)。虽然麻烦,但是很有效。以下是我的代码,欢迎指正!

    class CollectList extends UserDefinedAggregateFunction {
    
      override def inputSchema: StructType = StructType(StructField("id", StringType, nullable = true) :: StructField("state", StringType, nullable = true):: Nil)
    
      override def bufferSchema: StructType = StructType(StructField("ids", ArrayType(StringType, containsNull = true), nullable = true) :: Nil)
    
      override def dataType: ArrayType = ArrayType(StringType, containsNull = true)
    
      override def deterministic: Boolean = false
    
      override def initialize(buffer: MutableAggregationBuffer): Unit = {
        buffer(0) = null
      }
    
      override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
        if (buffer.get(0) == null){
          buffer(0) = Array(input.getString(0) + "_" + input.getString(1))
        }
        else {
          val s = input.getString(0) + "_" + input.getString(1)
          val b = buffer.getAs[Seq[String]](0)
          buffer(0) = b :+ s
        }
    
      }
    
      override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
        if (buffer1.getAs[Seq[String]](0) == null){
          buffer1(0) = buffer2.getAs[Seq[String]](0).distinct
        }
        else {
          buffer1(0) = (buffer1.getAs[Seq[String]](0) ++ buffer2.getAs[Seq[String]](0)).distinct
        }
      }
    
      override def evaluate(buffer: Row): Any = buffer.getAs[Seq[String]](0)
    
    }
    

    【讨论】:

      猜你喜欢
      • 2018-07-23
      • 1970-01-01
      • 2020-04-15
      • 1970-01-01
      • 1970-01-01
      • 2020-10-17
      • 2020-05-15
      • 2020-01-19
      • 1970-01-01
      相关资源
      最近更新 更多