我对Dataflow及其编程模型相对较新,并且遇到了需要计算客户最高花费前10周的问题。如果这似乎是一个愚蠢的问题,我道歉。
我拥有的数据包括我用作密钥的客户ID以及包含时间戳和支出值的几百万条记录。
我创建了一个类似于此的Extract方法(不包括日志记录和日期格式化程序)。它接收一个BigQuery表行,从中我提取客户ID,支出和时间戳,从中获取周数:
static class ExtractSpend extends DoFn<TableRow, KV<String, SpendByWeek>> {
private static final long serialVersionUID = 0;
@Override
public void processElement(ProcessContext c) {
String custId = (String) row.get("customerID");
LocalDateTime date = LocalDateTime.parse((String) row.get("timestamp"), dateTimeFormatter);
WeekFields weekFields = WeekFields.of(Locale.getDefault());
int weekNumber = date.get(weekFields.weekOfWeekBasedYear());
Double spend = (Double) row.get("spend");
SpendByWeek spendByWeek = new SpendByWeek(weekNumber, spend.doubleValue());
c.output(KV.of(custId, spendByWeek));
}
}
但我无法弄清楚如何获取此输出并将其分组,以便我可以为每个客户ID和周添加支出值,对它们进行排序并输出每个客户的PCollection<String, List<Double>>
及其每周花费前10名。
有人能帮我解决这个问题吗?
答案 0 :(得分:1)
如果您只想使用分组来完成此操作,则需要先按客户ID和周分组以计算Sum
,然后将周移动到值中,然后仅按客户ID重新组合计算Top
。您也可以使用窗口来执行此操作,而不是将周放在键中。有关这方面的一些细节,请参阅最后一页。
完成上述操作后,您有一个PCollection<KV<String, SpendByWeek>>
,其中每周对于给定的密钥发生一次。您可以通过定义实施SpendByWeek
的{{1}}并将其与Comparator<SpendByWeek>
一起使用来确定每个给定用户ID的前Serializable
。
使用Windows计算每用户每周花费
如上所述,您可以使用窗口来帮助计算每周支出。
Top.perKey()
按客户ID和输出输出键入的单独支出行。outputWithTimestamp
,它将把事件除以指定大小的窗口。在您的情况下,您可能需要FixedWindows
或FixedWindows.of(Duration.standardWeeks(1))
。CalendarWindows.weeks(...)
。此时,您将拥有一个Sum.doublesPerKey()
,其中包含每周窗口PCollection
,其中每个条目都是该周中该密钥的总支出。
KV<String, Double>
来获取每小时窗口并将该信息移动到值中(所以现在你有DoFn
)KV<String, SpendAndWeek>
GlobalWindows
操作。