我正在使用Flink 1.4.0
。
我正在将Kafka主题中的数据用于DataStream。数据转换为POJO
,比如说Employee
,我最终得到的结果如下:
DataStream<Employee> employeeStream = ...;
现在,我需要使用来自大csv
文件的数据来丰富此流实例中的一些字段。我找到了一种很好的方法来加载csv并创建另一个DataStream:
DataStream<Enrichements> enrichmentsStream = ...;
现在,POJOs
两个共享一个字段(id),可用于JOIN
操作。如果这些是DataSet,我本来可以应用leftOuterJoin()
,但事实并非如此。我并不关心窗口,因为我希望Employee
中的任何Enrichments
信息都来自 employeeStream
.join(enrichmentsStream )
.where(new SelectKeyForEmployee())
.equalTo(new SelectKeyForEnrichments())
.window(?????)
.apply(new JoinEnrichFunction());
,如果它的id存在于csv中。我该怎么做呢?忽略窗口的连接操作会起作用吗?会不会是资源匮乏?它看起来像这样吗?:
JOIN
此外,由于窗口必须由两个流共享,如何在应用JoinEnrichFunction()
函数之前定义它们的窗口以及stringsAsFactors
的实现是什么?
答案 0 :(得分:2)
事实证明,在这种情况下,连接操作是多余的。流连接不直观,只有在共享相同窗口机制的流之间应用时才有意义。
在这种情况下,地图功能足以满足此处详述的浓缩目标。以下代码片段应该足够清楚:
public MainClass {
public void main(String[] args) {
...
// Some custom way of loading the csv data into a Map<POJO> format
MetadataLoader loader = new MetadataLoader("pathToData.csv");
Map<Employee> metadataHashMap = loader.getMetadataMap(employeeEnrichmentData);
...
// Enrichment
SingleOutputStreamOperator<Employee>> enrichedStream = rawStream
.map(new MapMetadataToEmployees(metadataHashMap))
.name("Enrich: with Employee Metadata");
// Some sink opeartion
...
}
}
final class MapMetadataToEmployees implements MapFunction<Employee, Employee>, Serializable {
private Map<Employee> metaDataMap;
public MapMetadataToEmployees(Map<String, Employee> metaDataMap) {
this.metaDataMap = metaDataMap;
}
@Override
public Employee map(Employee employee) {
if (metaDataMap.containsKey(employee.getId())) {
Employee employeeWithMetaData = metaDataMap.get(employee.getId());
employee.setSalary(employeeWithMetaData.getSalary);
employee.setRank(employeeWithMetaData.getRank());
employee.setBusinessTitle(employeeWithMetaData.getBusinessTitle());
}
return employee;
}
}