我有一个与Spark JavaStreamingContext
一起使用的程序。我已经了解到,在使用DStream时,只有少数输出操作被允许为print()
。
这是一段代码
private static void analyzeHashtags() throws InterruptedException {
JavaPairDStream<String, String> messages = KafkaUtils.createStream(jssc, zookeeper_server, kafka_consumer_group, topics);
JavaPairDStream<String, Integer> lines = messages.mapToPair((x)->(new Tuple2<String, Integer>(x._2, 1))).reduceByKey(sumFunc);
lines.print();
jssc.start();
jssc.awaitTermination();
}
现在我想在此代码中添加查询操作,如下所示:
private static void analyzeHashtags() throws InterruptedException, SQLException {
JavaPairDStream<String, String> messages = KafkaUtils.createStream(jssc, zookeeper_server, kafka_consumer_group, topics);
JavaPairDStream<String, Integer> lines = messages.mapToPair((x)->(new Tuple2<String, Integer>(x._2, 1))).reduceByKey(sumFunc);
lines.print();
String hashtag = "#dummy"; int frequencies = 59;
String cql = " CREATE (n:Hashtag {name:'"+hashtag+"', freq:"+frequencies+"})";
st.executeUpdate(cql);
jssc.start();
jssc.awaitTermination();
}
但是这段代码只执行一次查询。我希望它每次循环时执行它。 怎么可能做到这一点?提前谢谢。
答案 0 :(得分:2)
要对DStream执行任意操作,我们使用foreachRDD
。它提供了每个批处理间隔的数据访问,由底层的rdd。
Java / Scala伪(混合)代码:
JavaPairDStream<String, Integer> lines = messages.mapToPair((x)->(new
Tuple2<String, Integer>(x._2, 1))).reduceByKey(sumFunc);
lines.foreachRDD{ rdd =>
.. do something with the RDD here...
}
通常,do something
对RDD上的数据进行操作。
我们可以使用诸如foreachPartition
之类的RDD函数以分布式方式对该数据进行操作。
但是,考虑到你在这里使用本地neo4j连接,并且如果每个流间隔的数据不是很大,我们可以将数据收集到驱动程序并在本地执行操作。在这种情况下似乎是合适的,因为数据已经通过了分布式减少阶段(reduceBykey
)
因此,foreachRDD
部分将成为:
lines.foreachRDD{ rdd =>
val localDataCollection = rdd.collect
localDataCollection.foreach{ keywordFreqPair =>
val cql = "CREATE (n:Hashtag {name:'"+keywordFreqPair._1+"', freq:"+keywordFreqPair._2+"})"
st.executeUpdate(cql)
}