2017-01-05 75 views
2

我將spark數據框保存爲parquet文件,並且數據幀具有從avro對象構建的行。同樣的確切代碼在這裏 - https://stackoverflow.com/a/41491999/2440775Spark Avro實現實地編寫數字字段中的空值

我面臨的挑戰是,我打算能夠在輸入數據中缺少整數字段時具有空值。 Avro的似乎允許通過使用聯合類型,但是當我不指定缺省值或指定的AVSC「空」的默認值,我得到這樣的錯誤:

Caused by: org.apache.avro.AvroRuntimeException: Field xxx type:LONG pos:7 not set and has no default value 
    at org.apache.avro.generic.GenericData.getDefaultValue(GenericData.java:984) 
    at org.apache.avro.data.RecordBuilderBase.defaultValue(RecordBuilderBase.java:135) 

Or 

Caused by: org.apache.avro.AvroRuntimeException: Field xxx type:UNION pos:7 not set and has no default value 
    at org.apache.avro.generic.GenericData.getDefaultValue(GenericData.java:984) 
    at org.apache.avro.data.RecordBuilderBase.defaultValue(RecordBuilderBase.java:135) 

如果我寫的默認值「0」,它saveAsParquet效果不錯

我也試過改變avro規範有第一個「空」類型第一個元素以來的第一個類型。

"type": ["null","long"], "default": null 

這將導致如下的異常:

org.apache.spark.SparkException: Job aborted due to stage failure: Task 0 in stage 0.0 failed 1 times, most recent failure: Lost task 0.0 in stage 0.0 (TID 0, localhost): java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long 

在Avro的模式變更的長,空的順序導致以下異常

產生的原因:org.apache.avro.AvroTypeException :長的非數字默認值:null

回答

1

我沒有解決方案,但找到了解決方法。我從avro對象構建Row的方式是通過從avro對象創建一個列表,然後在其上做一個Row.fromSeq。解決方法檢查默認值0和int或long的數據類型。如果是默認值,則添加null。所以人們必須小心選擇默認值。

public static List avroToList(AvroData a) throws UnsupportedEncodingException{ 
     List l = new ArrayList<>(); 
     for (Schema.Field f : a.getSchema().getFields()) { 
      Object value = a.get(f.name()); 
      if (value == null) { 
       l.add(null); 
      } 
      else { 
       switch (f.schema().getType().getName()){ 
        case "union": 
         l.add(value.toString()); 
         break; 

        case "int": 
         if(value == 0) {l.add(null);} 
         else {l.add(Integer.valueOf(value.toString()));} 
         break; 

        case "long": 
         if(value == 0L) {l.add(null);} 
         else {l.add(Long.valueOf(value.toString()));} 
         break; 

        default:l.add(value); 
         break; 
       } 

      } 
     } 
     return l; 
    } 

的AVSC文件具有類型如下信息

"type": "long", "default": 0