来自动态模式的Spark数据帧或过滤掉不满足模式的行

时间:2017-08-08 06:14:53

标签: apache-spark apache-kafka apache-spark-sql spark-dataframe spark-streaming

我编写了一个kafka生成器,用于记录日志文件的内容(格式:csv).kafka使用者是一个创建JavaDStream的流应用程序。 使用forEachRDD方法,我将每行文件分割为分隔符','并创建Row对象。我指定了具有7列的模式。 然后我使用JavaRDD和模式创建数据帧。 但问题是,日志文件中的所有行都没有相同的列数。 因此,有没有办法过滤掉不满足模式的行或根据行内容动态创建模式? 以下是代码的一部分:

JavaDStream<String> msgDataStream =directKafkaStream.map(new Function<Tuple2<String, String>, String>() {
            @Override
            public String call(Tuple2<String, String> tuple2) {
                return tuple2._2();
            }
        });
msgDataStream.foreachRDD(new VoidFunction<JavaRDD<String>>() {
            @Override
            public void call(JavaRDD<String> rdd) {
                JavaRDD<Row> rowRDD = rdd.map(new Function<String, Row>() {
                    @Override
                    public Row call(String msg) {
                        String[] splitMsg=msg.split(",");
                        Object[] vals = new Object[splitMsg.length];
                        for(int i=0;i<splitMsg.length;i++)
                        {
                            vals[i]=splitMsg[i].replace("\"","").trim();
                        }

                        Row row = RowFactory.create(vals);
                        return row;
                    }
                });

                //Create Schema
                StructType schema = DataTypes.createStructType(new StructField[] {
                        DataTypes.createStructField("timeIpReq", DataTypes.StringType, true),DataTypes.createStructField("SrcMac", DataTypes.StringType, true),
                        DataTypes.createStructField("Proto", DataTypes.StringType, true),DataTypes.createStructField("ACK", DataTypes.StringType, true),
                        DataTypes.createStructField("srcDst", DataTypes.StringType, true),DataTypes.createStructField("NATSrcDst", DataTypes.StringType, true),
                        DataTypes.createStructField("len", DataTypes.StringType, true)});

                //Get Spark 2.0 session


                Dataset<Row> msgDataFrame = session.createDataFrame(rowRDD, schema);

1 个答案:

答案 0 :(得分:2)

删除与预期架构不匹配的行的一种简单方法是使用flatMap类型的Option,如果您的目标是构建DataFrame,我们使用相同的{{ 1}}步骤将模式应用于数据。通过使用flatMap es。

在Scala中为此提供了便利
case class

关于:

  

日志文件中的所有行都没有相同的列数。

假设它们都代表相同类型的数据但可能缺少某些列,那么正确的策略是过滤掉不完整的数据(如此处举例说明的)或者如果存在确定性,则在定义的模式中使用可选值了解哪些领域缺失的方法。此要求应提交给生成数据的上游应用程序。在CSV中使用空逗号序列表示缺失值很常见(例如// Create Schema case class NetInfo(timeIpReq: String, srcMac: String, proto: String, ack: String, srcDst: String, natSrcDst: String, len: String) val netInfoStream = msgDataStream.flatMap{msg => val parts = msg.split(",") if (parts.size == 7) { //filter out messages with unmatching set of fields val Array(time, src, proto, ack, srcDst, natSrcDst, len) = parts // use a extractor to get the different parts in variables Some(NetInfo(time, src, proto, ack, srcDst, natSrcDst, len)) // return a valid record } else { None // We don't have a valid. Return None } } netInfoStream.foreachRDD{rdd => import sparkSession.implicits._ val df = rdd.toDF() // DataFrame transformation is possible on RDDs with a schema (based on a case class) // do stuff with the dataframe }

处理每行差异的动态模式没有意义,因为没有办法应用它来完成由具有不同模式的行组成的field0,,field2,,,field5