Google cloud dataflow googledataflow中的数据整形操作

Google cloud dataflow googledataflow中的数据整形操作,google-cloud-dataflow,Google Cloud Dataflow,我目前有一个流式管道处理事件,并将它们推送到名为EventsTable的BigQuery表: TransactionID EventType 1 typeA 1 typeB 1 typeB 1 typeC 2 typeA 2 typeC 3 typeA TransactionID事件

我目前有一个流式管道处理事件,并将它们推送到名为EventsTable的BigQuery表:

TransactionID EventType 1 typeA 1 typeB 1 typeB 1 typeC 2 typeA 2 typeC 3 typeA TransactionID事件类型 1 A型 1 B类 1 B类 1 C类 2 A型 2 C型 3 A型 我想将一个分支添加到我的处理管道中,并将与事务相关的数据“分组”到一个事务表中。大致上,TransactionTable中的type列中的值将是给定事务的相关eventType的计数。对于前面的示例事件,输出如下所示:

TransactionID typeA typeB typeC 1 1 2 1 2 1 0 1 3 1 0 0 事务ID类型A类型B类型C 1 1 2 1 2 1 0 1 3 1 0 0 “类型”列的数量将等于系统中存在的不同eventType的数量

我试图看看如何使用数据流实现这一点,但找不到任何干净的方法。我知道PCollection是不可变的,因此我无法将传入数据存储在不断增长的PCollection结构中,该结构将对传入事件进行排队,直到出现所需的其他元素,并且我可以将它们写入第二个BigQuery表。是否有一种窗口功能允许对数据流执行此操作(如在带有到期日期的临时窗口结构中对事件进行排队)


我可能可以用批处理作业和PubSub做一些事情,但这要复杂得多。另一方面,我理解数据流并不意味着有不断增长的数据结构,数据一旦进入,就必须经过管道并退出(或被丢弃)。我错过什么了吗

一般来说,进行这种“跨多个事件聚合数据”的最简单方法是使用
CombineFn
,它允许您组合与特定键关联的所有值。这通常比将事件排队更有效,因为它只需要累积结果,而不是累积所有事件

对于您的特定情况,您可以创建一个自定义。累加器将是一个
映射
。例如:

public class TypedCountCombineFn
    extends CombineFn<EventType, Map<EventType, Long>, TransactionRow> {
  @Override
  public Map<EventType, Long> createAccumulator() {
    return new HashMap<>();
  }
  @Override
  public Map<EventType, Long> addInput(
      Map<EventType, Long> accum, EventType input) {
    Long count = accum.get(input);
    if (count == null) { count = 0; accum.put(input, count); }
    count++;
    return accum;
  }
  @Override
  public Map<EventType, Long> mergeAccumulators(
      Iterable<Map<EventType, Long>> accums) {
    // TODO: Sum up all the counts for similar event types
  }
  @Override
  public TransactionRow extractOutput(Map<EventType, Long> accum) {
    // TODO: Build an output row from the per-event-type accumulator
  }
}

是否每个事务都有3个关联值?如果没有,您选择Value1、Value2和Value3作为列的原因是否有什么特殊之处?还有关于交易和键/值对结构的更多细节吗?我确实编辑了原始帖子,以便更清楚,并给出了更多细节。希望这有帮助!
PCollection<EventType> pc = ...;

// Globally
PCollection<TransactionRow> globalCounts = pc.apply(Combine.globally(new TypedCountCombineFn()));

// PerKey
PCollection<KV<Long, EventType>> keyedPC = pc.apply(WithKeys.of(new SerializableFunction<EventType, Long>() {
  @Override
  public long apply(EventType in) {
    return in.getTransactionId();
  }
});
PCollection<KV<Long, TransactionRow>> keyedCounts =
  keyedPC.apply(Combine.perKey(new TypedCountCombineFn()));