在 DataFlow 中使用复杂对象

Using complex objects in DataFlow

我们有几个通过 DataFlow 从中读取的 BigQuery 表。目前,这些表被展平了,很多数据是重复的。在 Dataflow 中,所有操作都必须是幂等的,因此任何输出仅取决于函数的输入,没有任何其他地方保留状态。这就是为什么首先将所有属于一起的记录分组在一起是有意义的,在我们的例子中,这可能意味着创建复杂的对象。

复杂对象的示例(还有许多其他类似的类型)。显然,我们可以有数百万个每种类型的实例:

Customer{
   customerId
   address {
      street
      zipcode
      region
      ... 
   }
   first_name
   last_name
   ...
   contactInfo: {
       "phone1": {type, number, ... },
       "phone2": {type, number, ... }
   }
}

我们为 DataFlow 找到的示例仅处理非常简单的对象,这些示例演示了计数、求和和平均。

在我们的案例中,我们最终还是希望使用DataFlow,按照一套规则进行更复杂的处理。这些规则适用于客户、发票或订单的完整联系,并最终产生一整套指标、金额和其他项目。

我们曾考虑在 BigQuery 中 100% 执行此操作,但由于适用于每个实体的规则,这很快就会变得非常混乱。

此时我还在想 DataFlow 是否真的是完成这项工作的正确工具。几乎没有 dataFlow 的示例可以说明它如何用于具有一个或两个集合的这些类型的更复杂的对象。我发现最接近的是使用 "LogMessage" 对象进行日志处理,但是它没有任何集合,因此没有进行任何层次处理。

我们面临的最大问题是分层处理。我们正在读取这样的数据:

customerid ... street zipcode region ... phoneid type number
 1               a       b       c        phone1  1    555-2424
 1               a       b       c        phone2  1    555-8181

第一个操作应该是将这些行组合在一起以构造一个实体,这样我们就可以使我们的操作幂等。在 DataFlow 中执行此操作的最佳方法是什么,或者为我们提供一个执行此操作的示例?

您可以使用任何对象作为数据流管道中的元素。 TrafficMaxLaneFlow example 使用复杂对象(尽管它没有集合)。

在您的示例中,您将执行 GroupByKey 来对元素进行分组。结果是KV<K, Iterable<V>>。这里的 KV 只是一个对象,里面有一个类似集合的值。然后你可以把那个 KV<K, Iterable<V>> 变成你想要的任何类型的对象。

唯一需要注意的是,如果您只有很少的真正大的元素,您可能 运行 会遇到一些并行性限制。具体来说,每个元素都需要足够小,以便在单台机器上处理。

您可能还对 BigQueryIO 上的 withoutFlatteningResults 感兴趣。它只支持从查询中读取(而不是 table),但它应该提供不展平的结果。