我尝试计算给定Tumbling窗口中找到的最高标签数量。
为此,我对主题标签进行了“字数统计”并总结了它们。这很好用。在此之后,我尝试在给定窗口中找到具有最高顺序的#标签。我为此使用RichFlatMapFunction,并使用ValueState来保存单个主题标签的当前最大外观,但这不起作用。 我调试了我的代码并发现ValueState“maxVal”的值在每个flatMap步骤“null”中。所以update()和value()方法在我的场景中不起作用。
我是否误解了RichFlatMap功能或其用法?
这是我的代码,除了最后一个flatmap函数之外的所有内容都按预期工作:
public class TwitterHashtagCount {
public static void main(String args[]) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment().setParallelism(1);
DataStream<String> tweetsRaw = env.addSource(new TwitterSource(TwitterConnection.getTwitterConnectionProperties()));
DataStream<String> tweetsGerman = tweetsRaw.filter(new EnglishLangFilter());
DataStream<Tuple2<String, Integer>> tweetHashtagCount = tweetsGerman
.flatMap(new TwitterHashtagFlatMap())
.keyBy(0)
.timeWindow(Time.seconds(15))
.sum(1)
.flatMap(new RichFlatMapFunction<Tuple2<String, Integer>, Tuple2<String, Integer>>() {
private transient ValueState<Integer> maxVal;
@Override
public void open(Configuration parameters) throws Exception {
ValueStateDescriptor<Integer> descriptor =
new ValueStateDescriptor<>(
// state name
"max-val",
// type information of state
TypeInformation.of(Integer.class));
maxVal = getRuntimeContext().getState(descriptor);
}
@Override
public void flatMap(Tuple2<String, Integer> value, Collector<Tuple2<String, Integer>> out) throws Exception {
Integer maxCount = maxVal.value();
if(maxCount == null) {
maxCount = 0;
maxVal.update(0);
}
if(value.f1 > maxCount) {
maxVal.update(maxCount);
out.collect(new Tuple2<String, Integer>(value.f0, value.f1));
}
}
});
tweetHashtagCount.print();
env.execute("Twitter Streaming WordCount");
}
}
答案 0 :(得分:3)
我想知道为什么你共享的代码会运行。 sum(1)
的结果是非键控流,并且您使用的托管状态接口需要键控流,并且将为每个键保留单独的状态实例。我很惊讶你没有收到错误的说法“Keyed状态只能在'keyed stream'上使用,即在'keyBy()'操作之后。”
由于您之前已经对流进行了窗口化,因此如果您在RichFlatMapFunction之前再次使用它(使用相同的密钥),则每个密钥将出现一次,并且maxVal将始终为null。
如果您的目标是在每个时间窗口中找到所有主题标签的最大值,那么这样的事情可能会达到您的意图:
tweetsGerman
.flatMap(new TwitterHashtagFlatMap())
.keyBy(0)
.timeWindow(Time.seconds(15))
.sum(1)
.timeWindowAll(Time.seconds(15))
.max(1)