我们有3个Java pojos,
class Foo{
int id;
String name;
List<Bar1> list1;
List<Bar2> list2;
}
class Bar1{
int id;
String field_x;
String field_y;
}
class Bar2{
int id;
String field_a;
String field_b;
}
我们的Flink作业中有3个DataStreams,
class Test{
public static void main(...){
DataStream<Foo> ds1 = ...;
DataStream<Bar1> ds2 = ...;
DataStream<Bar2> ds3 = ...;
}
}
对于每个id,只有一个Foo对象,而Bar1和Bar2对象可以是多个。
我们想要做的是,对于ds1中的每个Foo,在ds2中找到具有相同ID的所有Bar1并将其放入list1,在ds3中找到具有相同ID的所有Bar2并将它们放入list2。
最好的方法是什么?
答案 0 :(得分:1)
Flink的DataStream运算符最多支持两个输入流。 在三种流上实现操作有两种常用方法:
Bar1
和Bar2
彼此不相关。大致如下所示:DataStream<Foo> withList1 = ds1
.connect(ds2).keyBy("id", "id")
.process(
// your processing logic
new CoProcessFunction<Foo, Bar1, Foo>(){...});
DataStream<Foo> withList1AndList2 = withList1
.connect(ds3).keyBy("id", "id")
.process(
// your processing logic
new CoProcessFunction<Foo, Bar2, Foo>(){...});
foo
,bar1
和bar2
的POJO,其中仅使用一个字段并使用带有单个输入的运算符来处理联合流。// map Foo to CommonType
DataStream<CommonType> common1 = ds1.map(new MapFunction<Foo, CommonType>(){...});
// map Bar1 to CommonType
DataStream<CommonType> common2 = ds2.map(new MapFunction<Bar1, CommonType>(){...});
// map Bar2 to CommonType
DataStream<CommonType> common3 = ds3.map(new MapFunction<Bar2, CommonType>(){...});
DataStream<Foo> withList1AndList2 = ds1.union(ds2, ds3)
.keyBy("id")
.process(
// your processing logic
new KeyedProcessFunction<CommonType, Foo>(){...});
您也可以只合并ds2
和ds3
并使用二进制运算符。
更大的问题可能是确定何时收到所有Bar1
和Bar2
事件,以便您可以发出结果。再次,有一些选项(取决于您的用例)。
Foo
知道需要等待多少Bar1
和Bar2
,解决方案就很明显。Foo
不知道要等待多少事件,则可以尝试发送一条通知,该通知表明已发送了最后一个Bar1
或Bar2
。Bar1
或Bar2
应该在x秒/分钟/等时间内到达,您还可以设置超时时间。