Spark:忽略或处理DataSet选择错误

时间:2018-03-15 01:20:45

标签: java apache-spark apache-spark-sql spark-dataframe

我正在测试一些原型应用程序。我们有嵌套字段的json数据。我正在尝试使用以下json和代码来拉取一些字段:

Feed: {name: "test",[Record: {id: 1 AllColumns: {ColA: "1",ColB: "2"}}...]}

Dataset<Row> completeRecord = sparkSession.read().json(inputPath);
final Dataset<Row> feed = completeRecord.select(completeRecord.col("Feed.Record.AllColumns"));

我有大约2000个包含此类记录的文件。我已经单独测试了一些文件,它们工作正常。但是对于某些文件,我在第二行上遇到错误:

  

org.apache.spark.sql.AnalysisException:无法从中提取值   Feed#8.Record:需要struct类型但是得到了字符串;

我不确定这里发生了什么。但是我想要优雅地处理这个错误并记录哪个文件有该记录。另外,有没有办法忽略这个并继续其余的文件?

2 个答案:

答案 0 :(得分:2)

根据我所学的内容回答我自己的问题。有几种方法可以解决它。 Spark提供了忽略损坏文件和损坏记录的选项。

要忽略损坏的文件,可以将以下标志设置为true:

  

spark.sql.files.ignoreCorruptFiles =真

用于更细粒度的控制并忽略不良记录而不是忽略整个文件。您可以使用Spark api提供的三种模式之一。

  

根据DataFrameReader api

     
    

模式(默认 PERMISSIVE ):允许一种处理损坏的模式     解析期间的记录。      PERMISSIVE :将其他字段设置为null     遇到损坏的记录,并将格式错误的字符串放入新的字符串中     columnNameOfCorruptRecord配置的字段。架构设置时     user,为额外字段设置null      DROPMALFORMED :忽略整体     记录损坏。
     FAILFAST :遇到异常时抛出异常     损坏的记录。

  

PERMISSIVE模式对我来说效果非常好,但是当我提供自己的模式时,Spark使用null填充缺少的属性,而不是将其标记为损坏的记录。

答案 1 :(得分:1)

异常表示其中一个json文件的结构不同,并且此特定文件中不存在路径Feed.Record.AllColumns

基于此方法

private boolean pathExists(Dataset<Row> df, String path) {
  try {
    df.apply(path);
    return true;
  }
  catch(Exception ex){
    return false;
  }
}

您可以决定是执行select还是记录错误消息:

if(pathExists(completeRecord, "Feed.Record.AllColumns") {
  final Dataset<Row> feed = completeRecord.select(completeRecord.col("Feed.Record.AllColumns"));
  //continue with processing
}
else {
  //log error message
}