如何使用Dataflow计算每个键的最高唯一值结果?

时间:2015-07-14 10:47:54

标签: google-cloud-dataflow

我对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名。

有人能帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

如果您只想使用分组来完成此操作,则需要先按客户ID和周分组以计算Sum,然后将周移动到值中,然后仅按客户ID重新组合计算Top。您也可以使用窗口来执行此操作,而不是将周放在键中。有关这方面的一些细节,请参阅最后一页。

完成上述操作后,您有一个PCollection<KV<String, SpendByWeek>>,其中每周对于给定的密钥发生一次。您可以通过定义实施SpendByWeek的{​​{1}}并将其与Comparator<SpendByWeek>一起使用来确定每个给定用户ID的前Serializable

使用Windows计算每用户每周花费

如上所述,您可以使用窗口来帮助计算每周支出。

  1. 写一个类似于ExtractSpend的DoFn,它接受一个TableRow并输出一个KV,它是使用Top.perKey()按客户ID和输出输出键入的单独支出行。
  2. 然后应用窗口转换,例如outputWithTimestamp,它将把事件除以指定大小的窗口。在您的情况下,您可能需要FixedWindowsFixedWindows.of(Duration.standardWeeks(1))
  3. 然后应用CalendarWindows.weeks(...)
  4. 等转换

    此时,您将拥有一个Sum.doublesPerKey(),其中包含每周窗口PCollection,其中每个条目都是该周中该密钥的总支出。

    1. 然后你可以运行一个KV<String, Double>来获取每小时窗口并将该信息移动到值中(所以现在你有DoFn
    2. 应用Window.into切换到KV<String, SpendAndWeek>
    3. 然后按上述方法应用GlobalWindows操作。
相关问题