2016-04-25 6 views
0

Wie kann ich eine Teilmenge von Feldern aus einer Avro-Parkett-Datei in Java lesen?Wie lese ich bestimmte Felder aus der Avro-Parquet-Datei in Java?

Ich dachte, ich könnte ein AVRO-Schema definieren, die eine Teilmenge der gespeicherten Datensätze ist und dann lesen ... aber ich bekomme eine Ausnahme.

hier, wie ich versuchte, es zu lösen

Ich habe 2 Avro-Schemata:

  • classA
  • ClassB

Die Felder der Klasse B sind eine Untergruppe von KlasseA .

 final Builder<ClassB> builder = AvroParquetReader.builder(files[0].getPath()); 
     final ParquetReader<ClassB> reader = builder.build(); 
     //AvroParquetReader<ClassA> readerA = new AvroParquetReader<ClassA>(files[0].getPath()); 
     ClassB record = null; 
     final List<ClassB> list = new ArrayList<>(); 
     while ((record = reader.read()) != null) { 
      list.add(record); 
     } 

Aber ich bekomme ein ClassCastException on line (record=reader.read()): Cannot convert ClassA to ClassB

Ich nehme an dem Leser das Schema aus der Datei liest.

Ich habe versucht, das Modell (d. H. builder.withModel) zu senden, aber seit KlasseB extends org.apache.avro.specific.SpecificRecordBase löst es eine Ausnahme aus.

I Ereignis versucht, das Schema in der Konfiguration festgelegt und setzen Sie ihn durch builder.withConfig aber keine Zigarre ...

Antwort

1

So ...

Paar Dinge:

  • AvroReadSupport.setRequestedProjection(hadoopConf, ClassB.$Schema) kann sein wird verwendet, um eine Projektion für die ausgewählten Spalten festzulegen.
  • Die Methode reader.readNext gibt immer noch ein ClassA Objekt zurück, löscht jedoch die Felder, die in ClassB nicht vorhanden sind.

die Leser direkt verwenden können Sie Folgendes tun: Wenn Sie planen, ein Inputformat verwenden, um die Avro-Parkett-Datei zu lesen, gibt es eine bequeme Methode

AvroReadSupport.setRequestedProjection(hadoopConf, ClassB.SCHEMA$); 
final Builder<ClassB> builder = AvroParquetReader.builder(files[0].getPath()); 
final ParquetReader<ClassA> reader = builder.withConf(hadoopConf).build(); 

ClassA record = null; 
final List<ClassA> list = new ArrayList<>(); 
while ((record = reader.read()) != null) { 
    list.add(record); 
} 

auch - hier ist ein Funkenbeispiel:

 final Job job = Job.getInstance(hadoopConf); 
     ParquetInputFormat.setInputPaths(job, pathGlob); 
     AvroParquetInputFormat.setRequestedProjection(job, ClassB.SCHEMA$); 

     @SuppressWarnings("unchecked") 
     final JavaPairRDD<Void, ClassA> rdd = sc.newAPIHadoopRDD(job.getConfiguration(), AvroParquetInputFormat.class, 
       Void.class, ClassA.class);