【发布时间】:2016-10-31 19:06:48
【问题描述】:
我遇到了一类在批处理中不存在的问题,但对于流式处理来说似乎并不重要。让我们考虑一下经典的字数统计示例:
lines
.flatMap(_.split("\\W+"))
.map(word => (word, 1))
.keyBy(0)
.sum(1)
这将打印流中每个单词的结果,例如:
input: "foo bar baz foo"
output: (foo, 1) (bar, 1) (baz, 1) (foo, 2)
我想做的是将每一行作为一个整体处理,然后才打印结果,即在每一行上使用一个窗口:
input: "foo bar baz foo"
output: (foo, 2) (bar, 1) (baz, 1)
显然,基于时间的窗口和基于计数的窗口都不适用于此处。解决问题的正确方法是什么?
【问题讨论】:
-
您需要将
flatMap和map合并为一个运算符,并进行一些预聚合(即计算每个单词在句子中出现的频率)。因此,输入 foo bar baz foo" 将被转换为 "(foo, 2) (bar, 1) (baz, 1)" before keyBy -
我需要对单个单词进行并行操作,然后再将它们分组。
-
我不明白你所说的“每行窗口”是什么意思。我认为在您的示例中添加更多输入行并显示所需的输出会有所帮助。
-
@FabianHueske 我的意思是我想计算每行的单词,即等到一行中的所有单词都被处理后,再发出任何输出。这只是一个示例,一般问题是:将每个输入记录拆分为不同的部分(也称为 flatMap),并行处理这些部分,然后将它们聚合(按每个初始记录分组)以进行进一步处理。
-
即逻辑上看起来是这样的:
lines.map(line => line.split("\\W+").map(processWord).reduce(aggregateWords)),这是 Mathias 建议的,但是处理功能相当繁重,所以我想以某种方式并行化它:lines.flatMap((_.id, _.split("\\W+"))).map(processWord).groupAllRecords(_.id).reduce(aggregateWords))
标签: apache-flink word-count flink-streaming