[英]Flink: does Flink support abstract operator which can process different data streams with common fields?
假設我們有多個數據流並且它們共享一些共同的特征。
例如,我們有一個教師的 stream 和一個學生的 stream ,它們都有一個年齡字段。 如果我想從實時 stream 中找出最年長的學生或老師,我可以實現如下操作符。
public MaxiumAgeFunc extends RichMapFunction<Student,Integer> {
int maxAge;
@Override
public void flatMap(Student s, Collector<Integer> collector) throws Exception {
if(s.age > maxAge){
maxAge = s.age;
}
collector.collect(maxAge);
}
}
要找出最年長的Teacher ,我們需要實現一個類似的運算符,如下所示
public MaxiumAgeFunc extends RichMapFunction<Teacher,Integer> {
int maxAge;
@Override
public void flatMap(Teacher t, Collector<Integer> collector) throws Exception {
if(t.age > maxAge){
maxAge = t.age;
}
collector.collect(maxAge);
}
}
但實際上這兩個算子有共同的流程邏輯,所以我的想法是定義一個父 class,比如People 。
public class People{
public Integer age;
}
那么Student和Teacher可以定義為他們的孩子class,也可以保留自己的字段。
public class Student extends People {
public Integer grade; // student grade
...
}
public class Student extends People {
public Integer subject; // the subject that teacher teaches
...
}
在這種情況下,我可以定義一個運算符,如下所示。
public MaxiumAgeFunc extends RichMapFunction<People,Integer> {
int maxAge;
@Override
public void flatMap(People p, Collector<Integer> collector) throws Exception {
if(t.age > maxAge){
maxAge = p.age;
}
collector.collect(maxAge);
}
}
但是當我嘗試使用這個算子來實現一個 Flink 執行拓撲時,由於數據類型不匹配,它無法工作。
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStream<Student> studentStream = env.addSource(...);
DataStream<Teacher> teacherStream = env.addSource(...);
studentStream.map(new MaxiumAgeFunc()).print();
teacherStream.map(new MaxiumAgeFunc()).print();
這是我的問題,是否可以為具有公共字段的輸入流創建一個抽象運算符?
這更像是一個 Java 而不是 Flink 問題:
你想要做的是讓MaxiumAgeFunc
像這樣參數化
public MaxiumAgeFunc<T extends People> extends RichMapFunction<T, Integer> {
int maxAge;
@Override
public void flatMap(T p, Collector<Integer> collector) throws Exception {
if(t.age > maxAge){
maxAge = p.age;
}
collector.collect(maxAge);
}
}
然后像這樣使用它
studentStream.map(new MaxiumAgeFunc<>()).print();
teacherStream.map(new MaxiumAgeFunc<>()).print();
編輯:
btw your function is not working with checkpointing (so will produce wrong results upon recovery from a checkpoint) and I'd rather go with an aggregation function over the global window .
students
.windowAll(GlobalWindows.create())
.aggregate(new AggregateFunction<People, Integer, Integer>() {
@Override
public Integer createAccumulator() {
return -1;
}
@Override
public Integer add(People value, Integer accumulator) {
return Math.max(value.age, accumulator);
}
@Override
public Integer getResult(Integer accumulator) {
return accumulator;
}
@Override
public Integer merge(Integer a, Integer b) {
return Math.max(a, b);
}
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.