Flink:应用于KeyedStream的RichMapFunction中的访问键,用于处理Option

时间:2018-12-11 15:03:57

标签: scala apache-flink flink-streaming

当我将None应用于密钥流时,我想将RichMapFunction作为密钥处理。

例如,我有一个这样的案例类:

case class Foo(a: Option[String], b: Int, acc: Option[Int] = None)

acc是我想用map计算的字段。

我想在流上应用状态映射,所以我有一个RichMapFunction(例如,它是累加器):

class Accumulator extends RichMapFunction[Foo, Foo] {

  private var sum: ValueState[Int] = _

  override def map(input: Foo): Foo = {

    val newAcc = Option(sum.value()) match {
      case None => input.b
      case Some(x) => x + input.b
    }
    sum.update(newAcc)
    Foo(input.a, input.b, Some(newAcc))
  }

  override def open(parameters: Configuration): Unit = {
    sum = getRuntimeContext.getState(
      new ValueStateDescriptor[Int]("accumulator", createTypeInformation[Int])
    )
  }
}

然后,我的管道执行如下:

object ExampleAccumulator extends App {

  val env = StreamExecutionEnvironment.getExecutionEnvironment

  env.fromElements(Foo(Some("a"), 1, None), Foo(Some("a"), 2, None), Foo(None, 10, None), Foo(None, 6, None))
    .keyBy(_.a)
    .map(new Accumulator())
    .print()

  env.execute("ExampleAccumulator")
}

输出是:

Foo(Some(a),1,Some(1))
Foo(Some(a),2,Some(3))
Foo(None,10,Some(10))
Foo(None,6,Some(16))

但是我想在密钥为None时在acc中获得None

是否可以在RichMapFunction中获取密钥?

2 个答案:

答案 0 :(得分:1)

暂时不支持。 可以通过KeyContext类中的getCurrentKey()方法获取该键,该方法未在RichMapFunction中公开。但是,Flink内部提供了KeyedProcessFunction,可以在参数Context中返回键。我相信这就是您想要的。

答案 1 :(得分:1)

您可以通过Foo API通过KeySelector的值访问密钥,Scala解决方法:

val selector = scalaKeyedStream
  .javaStream 
  .asInstanceOf[org.apache.flink.streaming.api.datastream.KeyedStream]
  .getKeySelector

scalaKeyedStream.map(in => selector.getKey(in))

您需要将Scala Stream转换为Java,因为Scala API details中没有getKeySelector方法。