Flink Left-Outer-JOIN:使用来自csv文件的数据丰富流

时间:2018-03-22 15:35:16

标签: java left-join flink-streaming

我正在使用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的实现是什么?

1 个答案:

答案 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;
  }
}