簡體   English   中英

轉換JavaRDD的問題 <Status> 到JavaRDD <String>

[英]Problem with transformation JavaRDD<Status> to JavaRDD<String>

我正在嘗試將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<String>但是映射被推斷為javaRDD<R>

不幸的是,Java類型推斷並不總是很聰明,因此在這種情況下,我要做的是將lambda的所有位提取為變量,直到找到Java無法為其提供准確類型的變量為止。 然后,我給該表達式指定我認為應該具有的類型,並查看Java為什么抱怨它。 有時,這只是編譯器中的一個限制,您必須將表達式顯式“轉換”為所需的類型,其他時候,您會發現代碼存在問題。 就您而言,代碼對我來說很好,所以還必須有其他東西。

但是,我有一條評論:在這里,您只需一次支付JSON序列化的費用(從Status到JSON字符串),然后進行反序列化(從JSON字符串到Row )。 另外,您沒有為您的Dataset提供任何架構,因此它必須進行兩次數據傳遞(或取決於配置的數據樣本)才能推斷出架構。 如果數據很大,所有這些都可能會非常昂貴。 我勸你寫從一個轉換Status ,以Row ,如果性能是一個問題,如果直接Status比較簡單。

另一個“順便說一句”:您隱式序列化了ObjectMapper ,很可能您不想這樣做。 該類似乎確實支持Java序列化,但是具有特殊的邏輯 由於Spark的默認配置是使用Kryo(其性能比Java序列化要好得多),因此我懷疑在使用默認的FieldSerializer時,它會做正確的事情。 您有三種選擇:

  • 使對象映射器靜態以避免序列化它
  • 配置您的Kryo注冊器以使用Java序列化對ObjectMapper類型的對象進行序列化/反序列化。 那會起作用,但不值得付出努力。
  • 在各處使用Java序列化代替Kryo。 餿主意! 它很慢並且會占用大量空間(內存和磁盤取決於要寫入序列化對象的位置)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM