如何根据事件在同一DataStream上应用不同的运算符

时间:2018-01-04 18:44:50

标签: apache-flink flink-streaming flink-cep

上下文:

有一个 ds:DataStream [Event] ,有3种类型的事件: A,B,C

问题 : 如何在不同的时间间隔内监控不同事件的发生?

即。假设一秒钟内只有一个事件,它是有序的。

ds = A,B,C,A,C,B,A,C,A,B,C ....

然后,

每3秒出现一次A:1,1,1,1,1,1,2,1,1 ......

每2秒内B的出现次数为:1,1,0,0,1,1,0,0,1,1 ......

每4秒出现一次C是:1,2,2,1,2,1,1,2 ....

2 个答案:

答案 0 :(得分:1)

您没有明确说出来,但我假设您必须在不同窗口时间跟踪的唯一事件类型的数量是任意大的。我进一步假设您已经或可以轻松地为每种事件类型创建一个唯一的字符串。在那种情况下:

使用MapFunction将事件转换为Tuple,其中字符串是事件ID。

使用DataStream.split按事件ID拆分流。

棘手的一点 通过在for循环中调用SplitStream.select创建多个Datastream,并迭代EventID。

同样在for循环中,将窗口函数应用于每个流。

最后,仍然在for循环中,将每个Datastream与前一个数据流联合起来(可以为此重用相同的变量)

flink的文档几乎从不在循环中定义运算符,但这样做是完全合法的。

以下是循环的内容应该是什么样的:

DataStream<String> finalText=null;//gets rid of "might not be defined" warnings
    for (Integer i = 0; i<3; i++){
        DataStream<String> tempStream =
                splitStream.select(i.toString())
                .map(new passthroughMapFunction<String>())
                        //window function can go here
                .name("Map"+i);
        if (finalText==null){
            finalText = tempStream;
        } else {
            finalText = finalText.union(tempStream);
        }
    }

答案 1 :(得分:0)

val aDs = all.filter(_.type == "A")
val bDs = all.filter(_.type == "B")
val cDs = all.filter(_.type == "C")

然后将您想要的任何内容应用于不同的数据流

如果过滤谓词计算量很大,您应事先在地图中对其进行预先计算,以使特定类型的过滤器尽可能轻量化。