使用Apache Beam SDK for Google Dataflow我想从一组交易中计算每日余额。
示例数据集可能如下所示,其中包含收款人姓名,交易日期和金额:
<localRepository>D:/repository</localRepository>
mvn -v
Apache Maven 3.5.0 (ff8f5e7444045639af65f6095c62210b5713f426; 2017-04-03T21:39:06+02:00)
Maven home: D:\Envirement\apache-maven-3.5.0-bin\apache-maven-3.5.0\bin\..
Java version: 1.8.0_144, vendor: Oracle Corporation
Java home: C:\Program Files\Java\jre1.8.0_144
Default locale: fr_FR, platform encoding: Cp1252
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
所需的结果集如下所示:
John, 2017-12-01, 100
John, 2017-12-01, 200
Jane, 2017-12-01, 150
John, 2017-12-02, -100
John, 2017-12-02, 300
我尝试使用John, 2017-12-01, 300 (100 + 200)
Jane, 2017-12-01, 150
John, 2017-12-02, 500 (300 + -100 + 300)
KV<Pair, BigDecimal>
函数来计算Combine.perKey
的总和,但不计算前一天的总数。结束余额作为第二天的起始余额。
答案 0 :(得分:1)
Beam的窗口API在这里使用是正确的:
https://beam.apache.org/documentation/programming-guide/#windowing
具体来说,您必须回答以下问题:
您的帖子中没有足够的信息来回答这些问题 - 您必须提供更多细节 - 您是在批处理还是流式传输模式下运行?您是否希望在每天结束时得到一个答案,或者您是否希望每次有新的交易时都会更新运行总计?或介于两者之间?如果我不得不猜测,听起来你想要保持全局总数(全局事件时间窗口),并且每天更新一次当前值。
在我们回答了上述问题之后,我们可以编写一些伪代码:
PCollection<KV<String, Double>> transactionsByName = .... ; // Read input
PCollection<KV<String, Double> dailyTotalsByName = transactionsByName
// Group by name
.apply(GroupByKey.<String, Double>create())
// 1-day windows
.apply(Window.<KV<String, Iterable<Double>>>into(
FixedWindows.of(Duration.standardDays(1))))
// Combine each window (see combiners guide [here][1])
.apply(Combine.<String, Iterable<Double>, Double>perKey(new SumTotals()));
PCollection<KV<String, Double> globalTotalsByName = dailyTotalsByName
// Global windows allow you to combine a running total. Triggering condition
// specifies 'when' in processing time the answers are materialized. Here we
// have chosen to output the answer each time a new daily total arrives.
.apply(Window.<KV<String, Iterable<Double>>>into(new GlobalWindows()))
.triggering(Repeatedly.forever(AfterPane.elementCountAtLeast(1))))
// Combine daily totals
.apply(Combine.<String, Iterable<Double>, Double>perKey(new SumTotals()))
上述代码可能无法完全按原样构建,但概述了至少一种合理的方法。当然,根据输入和问题的具体情况,您可能需要调整触发的频率等。如上所述,这只会在每天结束时给出结果。如果您想要实时运行总计,可以使用更复杂的触发条件来输出当前值。