我正在尝试将Twitter中的推文保存到MongoDb数据库中。
我有RDD<Status>
,我正在尝试通过ObjectMapper将其转换为JSON格式。但是这种转换存在一些问题(
public class Main {
//set system credentials for access to twitter
private static void setTwitterOAuth() {
System.setProperty("twitter4j.oauth.consumerKey", TwitterCredentials.consumerKey);
System.setProperty("twitter4j.oauth.consumerSecret", TwitterCredentials.consumerSecret);
System.setProperty("twitter4j.oauth.accessToken", TwitterCredentials.accessToken);
System.setProperty("twitter4j.oauth.accessTokenSecret", TwitterCredentials.accessTokenSecret);
}
public static void main(String [] args) {
setTwitterOAuth();
SparkConf conf = new SparkConf().setMaster("local[2]")
.setAppName("SparkTwitter");
JavaSparkContext sparkContext = new JavaSparkContext(conf);
JavaStreamingContext jssc = new JavaStreamingContext(sparkContext, new Duration(1000));
JavaReceiverInputDStream<Status> twitterStream = TwitterUtils.createStream(jssc);
//Stream that contains just tweets in english
JavaDStream<Status> enTweetsDStream=twitterStream.filter((status) -> "en".equalsIgnoreCase(status.getLang()));
enTweetsDStream.persist(StorageLevel.MEMORY_AND_DISK());
enTweetsDStream.print();
jssc.start();
jssc.awaitTermination();
}
static void saveRawTweetsToMondoDb(JavaRDD<Status> rdd,JavaSparkContext sparkContext) {
try {
ObjectMapper objectMapper = new ObjectMapper();
SQLContext sqlContext = new SQLContext(sparkContext);
JavaRDD<String> tweet = rdd.map(status -> objectMapper.writeValueAsString(status));
DataFrame dataFrame = sqlContext.read().json(tweet);
Map<String, String> writeOverrides = new HashMap<>();
writeOverrides.put("uri", "mongodb://127.0.0.1/forensicdb.LiveRawTweets");
WriteConfig writeConfig = WriteConfig.create(sparkContext).withJavaOptions(writeOverrides);
MongoSpark.write(dataFrame).option("collection", "LiveRawTweets").mode("append").save();
} catch (Exception e) {
System.out.println("Error saving to database");
}
}
JavaRDD<String> tweet = rdd.map(status -> objectMapper.writeValueAsString(status));
这是个问题。JavaRDD<String>
需要不兼容的类型,但映射被推断为javaRDD<R>
答案 0 :(得分:1)
Java类型推断并不总是很聪明,因此在这些情况下,我要做的是将lambda的所有位提取为变量,直到找到Java无法为其提供准确类型的变量为止。然后,我给该表达式指定我认为应该具有的类型,并查看Java为什么抱怨它。有时,这只是编译器中的一个限制,您必须将表达式显式“转换”为所需的类型,其他时候,您会发现代码存在问题。就您而言,代码对我来说很好,所以还必须有其他内容。
但是,我有一条评论:在这里,您只需支付一次JSON序列化的费用(从Status
到JSON字符串),然后反序列化(从JSON字符串到Row
)。另外,您没有为Dataset
提供任何架构,因此必须进行两次数据传递(或取决于配置的数据样本)才能推断出架构。如果数据很大,所有这些都可能会非常昂贵。如果性能令人担忧并且如果Status
比较简单,我建议您直接从Row
转换为Status
。
另一个“顺便说一句”:您正在隐式序列化ObjectMapper
,很可能您不想这样做。看来该类确实支持Java序列化,但是支持special logic。由于Spark的默认配置是使用Kryo(其性能比Java序列化要好得多),因此我怀疑在使用默认的FieldSerializer
时它会做正确的事情。您有三种选择:
ObjectMapper
类型的对象进行序列化/反序列化。那会起作用,但不值得付出努力。