如何从Java中的Avro-Parquet文件中读取特定字段?

时间:2016-04-25 22:23:29

标签: hadoop apache-spark avro parquet

如何从java中的avro-parquet文件中读取字段的子集?

我以为我可以定义一个avro架构,它是存储记录的一个子集,然后读取它们......但是我得到了一个例外。

以下是我试图解决的问题

我有2个avro架构:

  • CLASSA
  • ClassB的

ClassB的字段是ClassA的子集。

        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);
        }

但我在ClassCastException(record=reader.read())获得了Cannot convert ClassA to ClassBbuilder.withModel

我想读者正在从文件中读取架构。

我尝试发送模型(例如extends org.apache.avro.specific.SpecificRecordBase)但是因为classB builder.withConfig它会抛出异常。

我的事件尝试在配置中设置架构并将其设置为echo '<div class="enclosed">'; while ( have_rows('lyrics') ) : the_row(); echo '</div>'; 但没有雪茄......

1 个答案:

答案 0 :(得分:1)

因此...

一些事情:

  • AvroReadSupport.setRequestedProjection(hadoopConf, ClassB.$Schema)可用于为所选列设置投影。
  • reader.readNext方法仍会返回ClassA个对象,但会将ClassB中不存在的字段归零。

要直接使用阅读器,您可以执行以下操作:

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);
}

此外,如果您计划使用inputformat来阅读avro-parquet文件,那么有一种方便的方法 - 这是一个火花示例:

        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);